Recursion NASM中的递归:Fibonacci
我很难让递归工作。嗯,n的递归!阶乘计算器没那么难,我花了大约半天的时间才算出来Recursion NASM中的递归:Fibonacci,recursion,assembly,x86,nasm,fibonacci,Recursion,Assembly,X86,Nasm,Fibonacci,我很难让递归工作。嗯,n的递归!阶乘计算器没那么难,我花了大约半天的时间才算出来 mov eax, [input] call factorialator jmp quit ; factorialator: cmp eax, 0 je return push eax dec eax call factorialator ; pop eax imul ebx, eax ret ; return: mov ebx,
mov eax, [input]
call factorialator
jmp quit
;
factorialator:
cmp eax, 0
je return
push eax
dec eax
call factorialator
;
pop eax
imul ebx, eax
ret
;
return:
mov ebx, 1
ret
现在,这个函数用n=n-1调用它自己,每次都推n直到n=0,当它将所有的n相乘时。容易的豌豆
但是现在,我必须用(n-1)和(n-2)调用函数,我无法想象这将如何工作,因为我必须管理返回地址、堆栈和值。我所知道的是,每次它减去1或2,结果是1,那么它应该加上一个计数器,然后给出结果
因此,返回n-1直到n-1=1,在这种情况下,返回n-2,然后再次返回n-1。我只是有点困惑,在这两天的时间里我一直在努力
谢谢你的帮助,谢谢 这是同样的原则。在阶乘情况下,您暂时保存
N
,因为以后需要它将事实(N-1)
乘以。在斐波那契级数情况下,您也临时保存
N
(或N-1
),因为您需要它来计算N-2
,以便您可以计算fib(N-2)
x86实现可能如下所示:
fib:
cmp eax,1 ; Base case?
jbe done ; Yes => return n
dec eax
push eax ; Save n-1 on the stack
call fib ; Calculate fib(n-1)
xchg eax,[esp] ; Place fib(n-1) on the stack, while retrieving n-1 into eax
dec eax
call fib ; Calculate fib(n-2)
add eax,[esp] ; fib(n-2) + fib(n-1)
add esp,4 ; "Undo" the push operation
done:
ret
首先用更高级的语言(或伪代码)编写代码,使用temp的命名变量。这样,您在asm版本中需要做的事情就更清楚了。请注意,
xchg eax[esp]
有一个隐式的lock
前缀,因此比使用单独的加载/存储指令(使用诸如mov edx[esp]
/mov[esp],eax
/lea eax[edx-1]
之类的临时寄存器)要慢得多。当然,如果你关心效率的话,你会用类似于addeax,edx
/addedx,eax
的方法迭代计算Fib(n),用O(n)时间代替O(Fib(n))时间,以及更低的常数因子。但一般来说,在mem中使用xchg
显示示例是危险的。