Assembly MASM汇编中的递归Fibonacci

Assembly MASM汇编中的递归Fibonacci,assembly,recursion,masm,fibonacci,irvine32,Assembly,Recursion,Masm,Fibonacci,Irvine32,所以我创建了一个程序来给出斐波那契序列的第n项。我应该使用递归MASM汇编实现以下逻辑 int fib(int n){ if ((n == 1) || (n == 2)) return n - 1; else return fib(n-1) + fib(n-2); } 我似乎遇到的问题是在程序循环执行时保留这些值,直到达到1。我对递归相当缺乏经验,我觉得我在这方面遗漏了一些东西。我不知道如何保留这些值来添加它们 .code main PROC mov

所以我创建了一个程序来给出斐波那契序列的第n项。我应该使用递归MASM汇编实现以下逻辑

int fib(int n){ 
 if ((n == 1) || (n == 2)) 
     return n - 1; 
 else 
     return fib(n-1) + fib(n-2); 
}
我似乎遇到的问题是在程序循环执行时保留这些值,直到达到1。我对递归相当缺乏经验,我觉得我在这方面遗漏了一些东西。我不知道如何保留这些值来添加它们

.code
main PROC
    mov ecx,0
    push 4          ; calculate the nth fib
    call Fib            ; calculate fib (eax)
    call WriteDec
    call Crlf
    exit
main ENDP

Fib PROC
    add ecx,1
    push ebp
    mov  ebp,esp
    mov  eax,[ebp+8]    ; get n
    cmp  eax,2      ; n == 2?
    je   exception2     
    cmp  eax,1      ; n == 1?
    je   exception2         
    dec eax
    push eax            ; Fib(n-1)
    call fib

    add eax,
    jmp Quit


Exception2:
    dec eax
Quit:
    pop  ebp            ; return EAX
    ret  4          ; clean up stack
Fib ENDP

END main

在程序结束时,您必须恢复
ESP
,而不仅仅是
EBP

ret4
(stdcall)在这种情况下并不方便,因为您可以在第二次调用时重用堆栈上的值

对于第一次调用的结果,可以使用将在“当前”堆栈上创建的局部变量

即使选项指令允许,也不要在符号中混用小写和大写

我相应地更改了您的代码:

include Irvine32.inc

.code
main PROC
    mov ecx,0
    push 10             ; calculate the nth fib
    call fib            ; calculate fib (eax)
    add esp, 4          ; clean up the stack

    call WriteDec
    call Crlf
    exit
main ENDP

fib PROC C
    add ecx,1
    push ebp
    mov  ebp,esp
    sub  esp, 4         ; space for a local dword [ebp-4]
    mov  eax,[ebp+8]    ; get n

    ; if ((n == 1) || (n == 2)) return 1;
    cmp  eax,2          ; n == 2?
    je   exception2
    cmp  eax,1          ; n == 1?
    je   exception2

    ;else return fib(n-1) + fib(n-2);
    dec eax
    push eax            ; Fib(n-1)
    call fib
    mov [ebp-4], eax    ; store first result

    dec dword ptr [esp] ; (n-1) on the stack -> (n-2)
    call fib
    add esp, 4          ; clean up stack

    add eax, [ebp-4]    ; add result and stored first result

    jmp Quit

exception2:
    mov eax, 1          ; start values: 1, 1
    ; dec eax           ; start values: 0, 1
Quit:
    mov esp, ebp        ; restore esp
    pop ebp             ; restore ebp

    ret                 ; return EAX, stack not cleaned up
fib ENDP

END main
在VS中集合

.686p

        .xmm

        .model  flat, c

includelib  libcmtd

printf      proto   :vararg

scanf       proto   :vararg

Fibo        proto   :dword

        .data
guid_msg    db  ' Number of protest? ', 00h

doc_form_1  db  '%d', 00h

doc_form_2  db  ' %d ', 00h

        .data?

num_i       dd  ?

num_j       dd  ?

        .code

main        proc

        invoke  printf, addr guid_msg

        invoke  scanf, addr doc_form_1, addr num_j

        mov edi, 0

     .while edi < num_j

        invoke  Fibo, edi

        invoke  printf, addr doc_form_2, eax

        inc edi

    .endw

        ret 0

main        endp

Fibo        proc    uses edx esi, num_n:dword

        mov edx, num_n

    .if         edx < 1

        xor eax, eax

     .elseif   edx < 2

        mov eax, 1

    .else

        sub edx, 1

        invoke  Fibo, edx

        mov esi, eax

        sub     edx, 1

        invoke  Fibo, edx

        add eax, esi

    .endif

        ret 0

Fibo        endp

        end
.686p
.xmm
.模型公寓,c
includelib libcmtd
printfproto:vararg
scanfproto:vararg
菲波原型:德沃德
.数据
guid_msg db“抗议次数”,00h
文件表格1数据库'%d',00h
文档表单2数据库'%d',00h
.数据?
我有多少?
多少?
.代码
主进程
调用printf,addr guid\u msg
调用scanf,addr doc\u form\u 1,addr num\u j
mov edi,0
.而edi
使用堆栈存储要修改但稍后需要恢复的寄存器的值。我在从堆栈访问它们时遇到问题。我使用push和[ebp],但如果我将寄存器按到错误的位置,它将崩溃。尝试访问堆栈中以前的值只会提供随机数据,因为ret 4在完成一轮fib时会清除堆栈。每个
push
都需要相应的
pop
(或
add esp,n
ret n
,…)。如果没有看到你在做什么,很难说问题出在哪里。谢谢你的深入回复!虽然我对自己很失望,因为我在之前的版本中非常接近这一点。它只是没有正确地保存变量,因为我试图使用[ebp+20]之类的东西来访问它们。我没有考虑减量,尤其是,我仍然需要研究堆栈在汇编中是如何工作的。再次感谢您的回复!如果可以的话,我会投赞成票,但我还没有足够的声誉。请将你的答案格式化。这完全难以辨认