Assembly MASM汇编中的递归Fibonacci
所以我创建了一个程序来给出斐波那契序列的第n项。我应该使用递归MASM汇编实现以下逻辑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
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]之类的东西来访问它们。我没有考虑减量,尤其是,我仍然需要研究堆栈在汇编中是如何工作的。再次感谢您的回复!如果可以的话,我会投赞成票,但我还没有足够的声誉。请将你的答案格式化。这完全难以辨认