【发布时间】:2021-06-08 19:04:38
【问题描述】:
我在 x86 汇编中编写了一个简单的递归打印函数,但是,我注意到 call print 之后的所有指令都不会被执行,在摸索它之后,我想如果我删除 push ax, pop ax 一切正常,堆栈有什么我想念的吗?
代码如下:
print:
push ax
mov ah, 0x0e
mov al, [bx+si]
inc si
cmp al, 0x00
int 0x10
jne print
mov al, 0x0d
int 0x10
mov si,0
pop ax
ret
它是一个简单的以空字符为基本条件的递归函数,参数为bx,计数器为SI。
【问题讨论】:
-
这不是递归,因为你没有
call你的函数。这是一个循环。你在循环中有一个push ax,所以它会推送多个东西,然后你只弹出一个东西。因此,您不平衡堆栈。您还将int 0x10放在cmp和jne之间的错误位置。 -
是的。这是正确的行为。对于每个
push,必须有一个pop(一般来说)。如果您的循环的推送次数多于弹出次数,ret将返回另一个地址,因为两者都使用相同的堆栈。 -
为什么需要递归?另外即使需要递归,为什么还要保存
ax? -
递归不是基础列表中的第一件事,它不在基础列表中。所以先尝试基础知识。
-
保持代码干净,尽可能减少对函数的干扰,因为它是引导扇区的一部分。 - 引导扇区最多为 510 字节的代码。这足够小,只需在每个函数上使用 cmets 来指定它会/不会修改哪些寄存器。如果您希望所有函数都有一个共同的调用约定,那么该约定最好让 AX 和 DX(可能还有 CX)被调用破坏,因此想要调用函数的循环可以将它们的数据保存在任何其他寄存器中如果他们想让它生存下去。