Recursion NASM中的递归:Fibonacci

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,

我很难让递归工作。嗯,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, 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
显示示例是危险的。