Assembly x86组件集';推动';es和';普沙';差异

Assembly x86组件集';推动';es和';普沙';差异,assembly,x86,stack,assemblies,Assembly,X86,Stack,Assemblies,我被告知将有效寄存器放入堆栈中,不要在“子程序”中覆盖它们,这对我来说很清楚,每个人都知道。但是当我读到我同伴的密码时,我发现了以下密码: 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

我被告知将有效寄存器放入堆栈中,不要在“子程序”中覆盖它们,这对我来说很清楚,每个人都知道。但是当我读到我同伴的密码时,我发现了以下密码:

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
es之间有什么区别吗?
提前谢谢。

pusha
在执行前保存更多寄存器,尤其是
sp
的值、
bp
si
di
。除此之外,行为几乎完全相同。

pusha操作比
ax
bx
cx
dx
寄存器推动更多:

“按以下方式将所有通用寄存器推送到堆栈上: 顺序:(E)AX,(E)CX,(E)DX,(E)BX,(E)SP,(E)BP,(E)SI,(E)DI SP值是SP实际推送之前的值。“

通过使用八条
push
指令推送寄存器,基本上可以实现相同的操作,但这将为
sp
推送不同的值。您可以简单地忽略堆栈指针,因为实际上不需要推送它。按下并弹出七个寄存器与
pusha
popa
具有相同的用途,即使它的作用不完全相同:

push ax
push bx
push cx
push dx
push bp
push si
push di
...
pop di
pop si
pop bp
pop dx
pop cx
pop bx
pop ax

是的,
pusha
popa
在功能上是等效的,只要它们推/弹出所有寄存器即可。但是,对于一个简单的DOS中断调用,有必要这样做吗

传输到中断例程

  • 中断例程负责恢复其使用的任何寄存器
    ()
与所有操作一样,只需做所需的事情即可。中断调用必须保留寄存器-除了记录要更改的寄存器。常规状态调用在AX中返回结果,可能会更改标志,而不会更改其他内容。如果一个中断改变了其他任何东西(
ds:dx
),则应在其文档中说明

在代码中,使用
ah=09/int 21
,唯一的更改是

返回时间:AL=24小时

因此,所有其他寄存器都可以安全地假定为“已存储”

中断尽可能多地保留是有原因的。在全局范围内,当其他代码运行时,随时可能发生中断(“真实”中断,而不是用户调用的中断)

还有一个很好的理由,就是不要不加区别地使用
pusha/popa
。堆栈的大小是有限的——当然,它很大,但是可以嵌套的例程的数量也是有限的。在32位和64位代码中,寄存器也要大得多


每一个例程都应该只保留那些已知会更改的寄存器,而镜像后,在调用这样的例程之前,您应该只保存稍后需要的寄存器。在示例代码中没有,因此您可以安全地删除所有推送和弹出操作。

我知道它可以保存更多寄存器,但在给定的示例中可以替换它吗?@onegrx是的,只要您也将
pop
s替换为
popa
。)@onegrx:你不能用
push
pop
指令来复制
pusha
popa
的确切行为,但你可以达到同样的目的。
pusha
要短得多(pusha为1字节,而一系列
push
为8字节)。可能与某些紧凑的代码有关,例如引导加载程序或小型ROM上的BIOS例程。请注意
pusha
popa
是80286+指令。如果你的目标是一台普通的8086机器,这些将不起作用。事实上,有些汇编程序可能需要
.286
指令才能将它们识别为有效指令。没有使用.286(点指令)被认为是坏习惯?我无法想象why@mcleod_ideafix:
pusha
popa
是在80186中引入的,因此您也可以使用
.186
那么这些操作码在较旧的CPU上做了什么?在操作码表的这些位置是否有其他说明?或者处理器只是做了一些随机的事情或者可能被绞死?你引用的蒂姆·麦奎尔是谁?14年前的文章可靠吗?对于30年前的计算机架构?对