2015-05-09 96 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的確切位置。 –