递归斐波纳契组装

时间:2017-10-29 15:21:33

标签: linux recursion assembly fibonacci

今天我在汇编中写了一个递归的斐波那契,但它并没有起作用。我用NASM将它编译成目标文件,而不是用gcc编写它的精灵 当我输入1或2时,该功能完美运行,但是当我输入3,4,5,6或更多时,该功能不起作用。 我认为函数调用自身存在问题。

这段代码:

SECTION .data ;init data




str: db "This equal: %d",10,0

SECTION .text   ;asm code


extern printf
global main

main:
push ebp
mov ebp,esp
;--------------------


push 03  ; the index 
call _fibonacci
add esp,4

push DWORD eax
push str
call printf


;---------------------

mov esp,ebp
pop ebp
ret

这是功能:

_fibonacci:

push ebp
mov ebp,esp


mov ebx, [ebp+8] ;; param n 
cmp ebx,0
jne CHECK2

mov eax,0
jmp _endFIbofunc        

CHECK2: 
    cmp ebx,0x1
    jne ELSE3
    mov eax,1
jmp _endFIbofunc

ELSE3:

mov ebx,[ebp+8] 
dec ebx  ;; n-1


;;  FIRST call
push ebx
call _fibonacci
add esp,4
mov edx,eax

;;  SEC CALL
dec ebx
push ebx
call _fibonacci
add esp,4 
add eax,edx


mov eax,[ebp-4]

_endFIbofunc:

mov esp,ebp
pop ebp
ret

我在Ubuntu 16.04上运行后发送错误:

  

分段错误(核心转储)

可能是什么问题?

3 个答案:

答案 0 :(得分:0)

您必须在递归调用中存储(推送)您要更改的寄存器。然后恢复其原始值(弹出)。这应该可以解决问题。

这样的事情:

  • 按下您要在函数中使用的所有寄存器(除了将获得返回值的eax)
  • 推送ebx,因为那是您的参数
  • 调用函数
  • 添加esp,4
  • 弹出您在第一步中推送的所有寄存器,现在按相反的顺序

答案 1 :(得分:0)

mov eax,[ebp-4]

您正在[ebp-4]使用内存而没有放入有用的东西! 您需要在函数序言中保留此空间:

_fibonacci:
    push ebp
    mov  ebp, esp
    sub  esp, 4

从第一次递归调用返回时,将EAX的结果放在此记忆词中 从第二次递归调用返回时,您将此内存dword的内容添加到EAX 这样,EDX寄存器将不再被破坏。

为什么要使用EBX注册?如果您使用它,您必须保留它,如Al Kepp在答案中所解释的那样 如果你首先将参数放在EAX中,你知道对于低于2的两个值(所以0和1),结果就等于参数。简单。

    mov  eax, [ebp+8] ;; param n 
    cmp  eax, 2
    jb   _endFIbofunc        

如果你在第一次递归调用后没有直接平衡堆栈,你可以只减少已存在的dword并进行第二次递归调用。

    dec  eax              ; n-1
    push eax              ;(*)
    call _fibonacci
    mov  [ebp-4], eax
    dec  dword ptr [esp]  ; n-2
    call _fibonacci
    add  esp,4            ;(*)
    add  eax, [ebp-4]

整个过程:

_fibonacci:
    push ebp
    mov  ebp, esp
    sub  esp, 4           ;(*)
    mov  eax, [ebp+8] ;; param n 
    cmp  eax, 2
    jb   _endFIbofunc        
    dec  eax              ; n-1
    push eax              ;(*)
    call _fibonacci
    mov  [ebp-4], eax
    dec  dword ptr [esp]  ;(*) n-2
    call _fibonacci
    add  esp,4            ;(*)
    add  eax, [ebp-4]
_endFIbofunc:
    mov  esp, ebp
    pop  ebp
    ret

答案 2 :(得分:0)

除了提供的其他答案之外,这是另一种解决方案:

_fibonacci:
        mov     eax,[esp+4]             ;eax = n
        cmp     eax,2                   ;br if n < 2
        jb      _endFIbofunc
        dec     eax                     ;push n-1
        push    eax
        call    _fibonacci              ;returns eax = fib(n-1)
        xchg    eax,[esp]               ;eax = n-1, [esp] = fib(n-1)
        dec     eax                     ;push n-2
        push    eax
        call    _fibonacci              ;returns eax = fib(n-2)
        add     eax,[esp+4]             ;eax = fib(n-1)+fib(n-2)
        add     esp,8
_endFIbofunc:
        ret

Trivia - fib(47)是最大的&lt; 2 ^ 32。递归调用的数量= 2 * fib(n + 1)-1。

 n     fib(n)      # calls

 0          0            1
 1          1            1
 2          1            3
 3          2            5
 4          3            9
 5          5           15
 6          8           25
 7         13           41
 8         21           67
 9         34          109
10         55          177
11         89          287
12        144          465
13        233          753
14        377         1219
15        610         1973
16        987         3193
17       1597         5167
18       2584         8361
19       4181        13529
20       6765        21891
21      10946        35421
22      17711        57313
23      28657        92735
24      46368       150049
25      75025       242785
26     121393       392835
27     196418       635621
28     317811      1028457
29     514229      1664079
30     832040      2692537
31    1346269      4356617
32    2178309      7049155
33    3524578     11405773
34    5702887     18454929
35    9227465     29860703
36   14930352     48315633
37   24157817     78176337
38   39088169    126491971
39   63245986    204668309
40  102334155    331160281
41  165580141    535828591
42  267914296    866988873
43  433494437   1402817465
44  701408733   2269806339
45 1134903170   3672623805
46 1836311903   5942430145
47 2971215073   9615053951
48 4807526976   ...