gpt4 book ai didi

assembly - assembly 中的递归斐波那契

转载 作者:行者123 更新时间:2023-12-04 10:30:14 28 4
gpt4 key购买 nike

我正在尝试在 Assembly 中实现递归斐波那契程序。但是,我的程序崩溃了,出现了未处理的异常,我似乎无法找出问题所在。我不怀疑这涉及我对堆栈的不当使用,但我似乎无法指出哪里......

.386
.model Flat
public Fibonacci
include iosmacros.inc ;includes macros for outputting to the screen

.code
Fibonacci proc

MOV EAX, [EBP+8]
CMP EAX, 1
JA Recurse
MOV ECX, 1
JMP exit

Recurse:
DEC EAX
MOV EDX, EAX
PUSH EAX
CALL Fibonacci
ADD ESP, 4
MOV EBX, ECX
DEC EDX
PUSH EDX
CALL Fibonacci
ADD ECX, EBX
exit:
ret
Fibonacci endp


.data


end

此外,我已经在外部过程中将我用来获取斐波那契值的数字推送到堆栈中。问题可能出在哪里的任何想法?

最佳答案

当您执行 call ,下一个操作的地址被压入堆栈作为返回值。创建函数时,通常习惯于创建“堆栈框架”。此帧可用于打印调用堆栈以及局部变量和参数的偏移量。框架是通过函数开头的两个操作创建的:

push ebp
mov ebp, esp

在函数结束时,使用 leave 删除调用堆栈,这相当于这两个操作的相反操作。使用堆栈帧时,值 esp存储到 ebp ,使其指向堆栈上称为框架基址的位置。因为,在这个地址之上,有 ebp 的旧值和返回地址,您通常会使用 [ebp+8] 获得第一个参数。 .但是,您没有设置堆栈框架。这意味着 ebp 的旧值未入栈,当前值为 ebp不能用于获取参数,因为您不知道它在哪里。因此,你应该使用 [esp+4] 来获得你的论点。 .

此外,通常将返回值放在 eax 中。和 ebx为调用者保留。您的代码不遵循这些约定中的任何一个。此外,技术上不需要保留功能 ecxedx ,所以通常你应该在调用另一个函数之前将它们压入堆栈,如果你想保留它们。使用此代码, edxebx如果调用的值大于 2,则会被覆盖,从而导致无效结果。

这是一个完整的 list ,其中包括我提到的所有修复。我没有创建堆栈帧,因为它不是必需的,而您的代码也没有。
.386
.model Flat
public Fibonacci
include iosmacros.inc ;includes macros for outputting to the screen

.code
Fibonacci proc

MOV EAX, [ESP+4]
CMP EAX, 1
JA Recurse
MOV EAX, 1 ; return value in eax
JMP exit

Recurse:
PUSH EBX ; preserve value of ebx
DEC EAX
PUSH EAX
CALL Fibonacci
MOV EBX, EAX ; ebx is preserved by callee, so it is safe to use
DEC [ESP] ; decrement the value already on the stack
CALL Fibonacci
ADD EAX, EBX ; return value in eax
ADD ESP, 4 ; remove value from stack
POP EBX ; restore old value of ebx
exit:
ret
Fibonacci endp

关于assembly - assembly 中的递归斐波那契,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5616684/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com