2015-05-09 98 views
1

代码1:实现它调用事实(阶乘)功能的主要功能x86汇编递归函数 - >非法指令错误

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 

代码2,它实现事实(阶乘函数):

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 

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

问题说明:程序收到信号SIGILL,非法指令。为什么我得到这个错误?

+3

的'pusha'的和'popa'的甚至不均衡。检查包含“呼叫事实”的块。返回将会以这种方式进行。 – harold

+1

另外,学习使用调试器。 – Jester

回答

2
mov ebx,dword[a] 

pusha 
push ebx 
call fact 
add esp,4 

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

  1. 您需要初始化EAX才能从调用事实获得有意义的结果。一个方便的数字将是1.
  2. 既然您使用了pusha您还需要使用popa。我宁愿不用,因为你的代码并不需要它。
  3. 事实例程不使用在堆栈上传递的参数。它只是为此目的使用EBX寄存器。这意味着您可以省略push ebxadd esp,4,并且还可以从事实中删除enterleave指令。

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

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

一个较短的版本是

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

谢谢!但我不明白你为什么要这样做:mov [esp + 28],eax –

+0

如果没有这个指令,'popa'会将EAX中* fact *的结果替换为'pusha'保存的EAX的值。偏移+28是'pusha'存储EAX的确切位置。 –