有人告诉我将有效寄存器放入堆栈中,以免稍后在“子程序”中覆盖它们,对我来说很明显,每个人都知道这一点。但是,当我阅读队友的代码时,发现了以下代码:
puts: ; display character in ax
push ax
push bx
push cx
push dx
mov dx, ax
mov ah, 9h
int 21h
pop dx
pop cx
pop bx
pop ax
ret
然后我看到了
pusha
和popa
命令。我想可以这样来做:puts: ; display character in ax
pusha
mov dx, ax
mov ah, 9h
int 21h
popa
ret
pusha
和push
的集之间有什么区别吗?先感谢您。
最佳答案
是的,pusha
和popa
在功能上是等效的,仅是因为它们压入/弹出所有寄存器。但是,是否有必要对一个简单的DOS中断进行调用?
与所有操作一样,根据需要执行所有操作,仅此而已。中断调用必须保留寄存器-除了记录的更改寄存器之外。常规状态调用以AX
返回其结果,并且可以更改标志,并且不进行任何其他更改。如果中断更改了其他任何内容(例如ds:dx
),则应在其文档中说明。
在您的代码中,使用ah=09 / int 21
,唯一的变化是
因此所有其他寄存器都可以安全地假定为“已存储”。
有一个原因可以尽可能多地保留中断。在全局范围内,在其他代码运行时,任何时候都可能发生中断(“真正的”中断,而不是用户调用的中断)。
还有一个很好的理由不要不加选择地使用pusha/popa
。堆栈的大小有限-当然,堆栈很大,但是可以嵌套的例程数量也是如此。而且在32位和64位代码中,寄存器也要大得多。
每个例程都应只保留那些已知会更改的寄存器,并对其进行镜像,在调用该例程之前,只应保存以后需要的寄存器。在示例代码中,没有任何代码,因此您可以安全地删除所有推送和弹出操作。
关于assembly - x86组件集 'push'和 'pusha'的区别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29728171/