NASM大会recursion斐波那契

32位Ubuntu上学习NASM汇编。

我一直在学习recursion函数。 我只是做了因式分解,在这里得到你的帮助: 了解NASM大会的recursion阶乘函数

看着代码,我想也许我可以快速实现斐波那契,使用几乎相同的代码。 这里是代码,假设参数总是大于0

 SECTION .text global main main: ; ----------------------------------------------------------- ; Main ; ----------------------------------------------------------- push 6 call fibonacci mov [ECX],EAX add byte [ECX],'0' mov EDX,1 call print ; ----------------------------------------------------------- ; Exit ; ----------------------------------------------------------- mov EAX,1 int 0x80 ; ----------------------------------------------------------- ; Fibonacci recursivo: f(n) = f(n - 1) + f(n - 2) ; ----------------------------------------------------------- fibonacci: push EBP ; Retrieve parameter and put it push EBX ; Save previous parameter mov EBP,ESP ; into EBX register add EBP,12 ; mov EBX,[EBP] ; EBX = Param cmp EBX,1 ; Check for base case jle base ; It is base if (n <= 1) dec EBX ; Decrement EBX to put it in the stack push EBX ; Put (EBX - 1) in stack inc EBX ; Restore EBX call fibonacci ; Calculate fibonacci for (EBX - 1) mov ESI,EAX ; EAX = (EAX + EBX) pop EBX ; Retrieve EBX from the stack sub EBX,2 ; Decrement EBX to put it in the stack push EBX ; Put (EBX - 2) in stack add EBX,2 ; Restore EBX call fibonacci ; Calculate fibonacci for (EBX - 2) mov EDX,EAX ; EAX = (EAX + EBX) pop EBX ; Retrieve EBX from the stack add ESI,EDX mov EAX,ESI jmp end base: ; Base case mov EAX,1 ; The result would be 1 end: pop EBX ; Restore previous parameter pop EBP ; Release EBP ret 

这有点粗俗。 我为(parameter - 1)计算斐波那契(parameter - 1) ,然后我再次为(parameter - 2) ,然后把它们加起来放到EAX

它不工作:

 2 => 2 3 => 3 4 => 4 5 => 4 

幸运的是我修复了分段错误的错误,但是我可能会破坏别的东西。 现在我看不出有什么问题。 你能告诉我为什么我得到错误的价值?

一个特别的观察是,出于某种原因,做mov ECX,EAX给了我一个分段错误的错误。 这就是我用ESI代替的原因。 我不知道为什么,但我想这是相关的。

无论何时处理递归,都必须非常小心递归链中的下一层将对当前层的状态(例如寄存器值)做什么。 我建议重写这个函数如下:

 fibonacci: push EBP ; Retrieve parameter and put it push EBX ; Save previous parameter mov EBP,ESP ; into EBX register add EBP,12 ; mov EBX,[EBP] ; EBX = Param cmp EBX,1 ; Check for base case jle base ; It is base if (n <= 1) lea ecx,[ebx-1] push ecx ; push N-1 call fibonacci ; Calculate fibonacci for (EBX - 1) pop ecx ; remove N-1 off the stack push eax ; save the result of fibonacci(N-1) lea ecx,[ebx-2] push ecx ; push N-2 call fibonacci ; Calculate fibonacci for (EBX - 2) pop ecx ; remove N-2 off the stack pop ecx ; ecx = fibonacci(N-1) add eax,ecx ; eax = fibonacci(N-2) + fibonacci(N-1) jmp end base: ; Base case mov EAX,1 ; The result would be 1 end: pop EBX ; Restore previous parameter pop EBP ; Release EBP ret