在 32 位 Ubuntu 上学习 NASM 程序集。我现在正在尝试学习递归函数,从阶乘开始(注意:这里我假设参数总是非负的)。
假设我有
push 3
call factorial
我想以 6
结尾在EAX
.
这是我的尝试:
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
.
你能建议我如何做一个从堆栈中获取参数的递归阶乘函数吗?我相信已经看过一些示例,但是它们要么不是递归的,要么从其他地方获取参数,或者使用了一堆变量(当我认为只用寄存器就可以完成时)。
最佳答案
请注意,factorial(n-1)
将首先覆盖 EBX
的 factorial(n)
值,因此在 push
之后呈现 inc EBX
毫无意义。达到基本情况后,当您执行 mul
时,您会遇到 EBX
为 0 的情况,当然还有任何 * 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
关于linux - 了解 NASM 程序集中的递归阶乘函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19217960/