2013-10-07 96 views
1

在32位Ubuntu上學習NASM裝配。我現在試圖學習遞歸函數,從階乘開始(注意:這裏我假設參數總是非負的)。瞭解NASM裝配中的遞歸階乘函數

假設我有

push 3 
call factorial 

我想EAX6結束了。

這裏是我的嘗試:

SECTION .text 
global main 
main: 
; ----------------------------------------------------------- 
; Main 
; ----------------------------------------------------------- 
push 3 
call factorial 

; ----------------------------------------------------------- 
; Exit 
; ----------------------------------------------------------- 
mov EAX,1 
int 0x80 

; ----------------------------------------------------------- 
; Recursive Factorial: n! = n * (n - 1)! 
; ----------------------------------------------------------- 
factorial: 

push EBP   ; Retrieve parameter and put it 
mov  EBP,ESP  ; into EBX register 
add  EBP,8  ; 
mov  EBX,[EBP] ; EBX = Param 

cmp  EBX,0  ; Check for base case 
je  base  ; It is base if (n == 0) 

dec  EBX   ; Decrement EBX to put it in the stack 
push EBX   ; Put (EBX - 1) in stack 
inc  EBX   ; Restore EBX 
call factorial ; Calculate factorial for (EBX - 1) 
mul  EBX   ; EAX = (EAX * EBX) = (EBX - 1)! * EBX 
pop  EBX   ; Retrieve EBX from the stack 

jmp end 
base:    ; Base case 
mov  EAX,1  ; The result would be 1 

end: 

pop  EBP   ; Release EBP 
ret 

至少它爲基礎的情況下,哈......但對於任何其他值我推開,它總是返回0。我有懷疑,也許因爲EAX0,MUL總是會導致0,解釋這一點。爲了測試,我決定給EAX的值爲2,期望有一些非零值,但它保留導致0

你能告訴我如何做一個遞歸析因函數,它的參數來自堆棧嗎?我相信已經看到了一些例子,但是他們不是遞歸的,或者他們從其他地方獲得了參數,或者他們使用了一堆變量(當我認爲它可以通過寄存器完成時)。

+0

提示:用C的功能,與'的GCC -Wall -O3 -m32 -S ...'然後使用所得到的編譯器生成的彙編源代碼編譯作爲你自己的功能的模板(甚至只是爲了管理堆棧的一般指導,傳遞參數和功能結果等)。 –

+0

@PaulR:謝謝你的建議。有人曾經告訴過我一個將C++翻譯成Assembly的網站(http://assembly.ynh.io/),你認爲這對於這個目的有什麼好處嗎? – Voldemort

+0

由於你運行的是Linux,你已經擁有了所有你需要的工具(比如gcc),但你永遠不會有太多的工具,如果這個站點能夠生成適合NASM的英特爾格式的asm,那麼它可能對你更有用特殊案例。無論如何都要嘗試 - 這是學習東西的好方法。 –

回答

3

注意factorial(n-1)將覆蓋的EBX它做的第一件事factorial(n)'s值,從而使後push毫無意義的inc EBX。你已經達到了基本情況後,你就會有情況EBX爲0,當你做mul,當然任何事情* 0 == 0,

最簡單的解決將是序幕更改爲:

push EBP   ; Retrieve parameter and put it 
push EBX   ; save previous param 
mov  EBP,ESP  ; into EBX register 
add  EBP,12  ; 
mov  EBX,[EBP] ; EBX = Param 

和結語到:

pop  EBX   ; restore previous param 
pop  EBP   ; Release EBP 
ret