1
在32位Ubuntu上學習NASM裝配。我現在試圖學習遞歸函數,從階乘開始(注意:這裏我假設參數總是非負的)。瞭解NASM裝配中的遞歸階乘函數
假設我有
push 3
call factorial
我想EAX
與6
結束了。
這裏是我的嘗試:
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
。我有懷疑,也許因爲EAX
是0
,MUL
總是會導致0
,解釋這一點。爲了測試,我決定給EAX
的值爲2
,期望有一些非零值,但它保留導致0
。
你能告訴我如何做一個遞歸析因函數,它的參數來自堆棧嗎?我相信已經看到了一些例子,但是他們不是遞歸的,或者他們從其他地方獲得了參數,或者他們使用了一堆變量(當我認爲它可以通過寄存器完成時)。
提示:用C的功能,與'的GCC -Wall -O3 -m32 -S ...'然後使用所得到的編譯器生成的彙編源代碼編譯作爲你自己的功能的模板(甚至只是爲了管理堆棧的一般指導,傳遞參數和功能結果等)。 –
@PaulR:謝謝你的建議。有人曾經告訴過我一個將C++翻譯成Assembly的網站(http://assembly.ynh.io/),你認爲這對於這個目的有什麼好處嗎? – Voldemort
由於你運行的是Linux,你已經擁有了所有你需要的工具(比如gcc),但你永遠不會有太多的工具,如果這個站點能夠生成適合NASM的英特爾格式的asm,那麼它可能對你更有用特殊案例。無論如何都要嘗試 - 這是學習東西的好方法。 –