问题描述
学习NASM大会在32位的Ubuntu。现在我想了解递归函数,从阶乘(注:这里我假设参数将始终为非负)。
Learning NASM Assembly on 32-bit Ubuntu. I'm now trying to learn about recursive functions, starting with factorial (note: here I am assuming that the parameter will always be non-negative).
假设我有
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
。
At least it works for the base case, ha... But for any other value I push, it always returns 0
. I had the suspicion that maybe since EAX
is 0
, MUL
would always result in 0
, explaining this. To test, I decided to give EAX
a value of 2
, expecting some non-zero value, but it kept resulting in 0
.
您能不能指点我如何做一个递归阶乘函数,接受它的参数从栈?我相信在看到一些例子,但他们要么没有递归或者他们把他们的参数从其他地方,或者他们用一组变量(当我认为它可以只注册完成)。
Can you advice me on how to do a recursive factorial function that takes its parameter from the stack? I believe having seen some examples, but either they were not recursive or they took their parameters from other places, or they used a bunch of variables (when I think it can be done with just registers).
推荐答案
注意阶乘(N-1)
将覆盖阶乘(N)
EBX
它做的第一件事,从而使 INC EBX
的值之后,小号在推
毫无意义的。你已经达到了基本情况后,你就会有这种情况,其中 EBX
0时,你做的 MUL
,当然任何事情* 0 == 0。
Note that factorial(n-1)
will overwrite factorial(n)'s
value of EBX
the first thing it does, thereby rendering the inc EBX
after the push
pointless. After you've reached the base case you'll have the situation where EBX
is 0 when you do the mul
, and of course anything * 0 == 0.
最简单的解决将是序幕更改为:
The easiest fix would be to change the prologue to:
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
这篇关于了解递归阶乘函数在NASM大会的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!