x86程序集递归函数 - >非法指令错误

时间:2022-12-29 03:15:07

Code1: implements main function which calls fact (factorial) function

Code1:实现调用fact(factorial)函数的main函数

section .data
    msg db "Enter the Number whose factorial is to be calculated",10,0
    msg1 db "The factorial is: ",0
    ioput db "%d"

section .bss
    a resd 1

section .text
    global main
    extern printf,scanf,fact
main:   
    pusha 
    push msg
    call printf
    add esp,4
    popa

    pusha 
    push a
    push ioput
    call scanf
    add esp,8
    popa

    mov ebx,dword[a]

    pusha
    push ebx
    call fact
    add esp,4


    pusha
    push msg1
    call printf
    add esp,4
    popa

    pusha
    push eax
    push ioput
    call printf
    add esp,8
    popa

    ret

Code2 which implements fact (factorial function):

实现事实的Code2(阶乘函数):

section .text
    global fact
    extern printf,scanf
fact:   
    enter 0,0
    cmp ebx,1
    jnz next
    ret

next:
    push ebx
    dec ebx
    call fact
    pop ebx
    mul eax,ebx
    leave
    ret

System stats: 32 bit machine, Ubuntu 14.04, Nasm is used

系统统计:32位机器,Ubuntu 14.04,使用Nasm

Problem statement: Program received signal SIGILL, Illegal instruction. Why am I getting this error?

问题陈述:程序接收信号SIGILL,非法指令。为什么我收到此错误?

1 个解决方案

#1


mov ebx,dword[a]

pusha
push ebx
call fact
add esp,4

This is the part of your program that has some problems!

这是你的程序中有一些问题的一部分!

  1. You need to initialize EAX to get meaningful results from calling fact. A convenient number would be 1.
  2. 您需要初始化EAX以从调用fact获得有意义的结果。一个方便的数字是1。

  3. Since you used pusha you also need to use popa. I would have preferred none because your code doesn't really need it.
  4. 既然你使用了pusha,你还需要使用popa。我宁愿没有,因为你的代码并不真正需要它。

  5. The fact routine doesn't use a parameter passed on the stack. It simply uses the EBX register for that purpose. This means that you can omit push ebx and add esp,4 and also that you could remove the enter and leave instructions from fact.
  6. 事实例程不使用在堆栈上传递的参数。它只是为此目的使用EBX寄存器。这意味着您可以省略push ebx并添加esp,4以及您可以从事实中删除enter和leave指令。

This is the code you could write to solve it all.

这是您可以编写的代码来解决所有问题。

mov ebx,dword[a]
mov eax,1
pusha
call fact
mov [esp+28],eax
popa

A shorter version is

更短的版本是

mov ebx,dword[a]
mov eax,1
call fact

#1


mov ebx,dword[a]

pusha
push ebx
call fact
add esp,4

This is the part of your program that has some problems!

这是你的程序中有一些问题的一部分!

  1. You need to initialize EAX to get meaningful results from calling fact. A convenient number would be 1.
  2. 您需要初始化EAX以从调用fact获得有意义的结果。一个方便的数字是1。

  3. Since you used pusha you also need to use popa. I would have preferred none because your code doesn't really need it.
  4. 既然你使用了pusha,你还需要使用popa。我宁愿没有,因为你的代码并不真正需要它。

  5. The fact routine doesn't use a parameter passed on the stack. It simply uses the EBX register for that purpose. This means that you can omit push ebx and add esp,4 and also that you could remove the enter and leave instructions from fact.
  6. 事实例程不使用在堆栈上传递的参数。它只是为此目的使用EBX寄存器。这意味着您可以省略push ebx并添加esp,4以及您可以从事实中删除enter和leave指令。

This is the code you could write to solve it all.

这是您可以编写的代码来解决所有问题。

mov ebx,dword[a]
mov eax,1
pusha
call fact
mov [esp+28],eax
popa

A shorter version is

更短的版本是

mov ebx,dword[a]
mov eax,1
call fact