有人告诉我将有效寄存器放入堆栈中,以免稍后在“子程序”中覆盖它们,对我来说很明显,每个人都知道这一点。但是,当我阅读队友的代码时,发现了以下代码:

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

然后我看到了pushapopa命令。我想可以这样来做:
puts: ; display character in ax
        pusha
        mov dx, ax
        mov ah, 9h
        int 21h
        popa
        ret
pushapush的集之间有什么区别吗?
先感谢您。

最佳答案

是的,pushapopa在功能上是等效的,仅是因为它们压入/弹出所有寄存器。但是,是否有必要对一个简单的DOS中断进行调用?

与所有操作一样,根据需要执行所有操作,仅此而已。中断调用必须保留寄存器-除了记录的更改寄存器之外。常规状态调用以AX返回其结果,并且可以更改标志,并且不进行任何其他更改。如果中断更改了其他任何内容(例如ds:dx),则应在其文档中说明。
在您的代码中,使用ah=09 / int 21,唯一的变化是

因此所有其他寄存器都可以安全地假定为“已存储”。
有一个原因可以尽可能多地保留中断。在全局范围内,在其他代码运行时,任何时候都可能发生中断(“真正的”中断,而不是用户调用的中断)。
还有一个很好的理由不要不加选择地使用pusha/popa。堆栈的大小有限-当然,堆栈很大,但是可以嵌套的例程数量也是如此。而且在32位和64位代码中,寄存器也要大得多。
每个例程都应只保留那些已知会更改的寄存器,并对其进行镜像,在调用该例程之前,只应保存以后需要的寄存器。在示例代码中,没有任何代码,因此您可以安全地删除所有推送和弹出操作。

关于assembly - x86组件集 'push'和 'pusha'的区别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29728171/

10-11 04:06