我在堆栈上存储了一个 2 字节值,我想将其弹出
到寄存器中。我可以通过使用其中的 16 位寄存器在其中一个通用寄存器上执行此操作,例如:
popw %cx
有没有办法将其放入另一个寄存器(例如r11
)并进行零填充?像这样的东西:
popzwq %r11 # making up the syntax
或者什么是正确的方法?
最佳答案
通常,您首先可以通过从不使用pushw来避免这种情况,而是在压入/弹出时始终使用全角(64位)堆栈槽。这也可以保持堆栈对齐。另外,通常您只会在进入/离开函数时使用推送/弹出来保存/恢复寄存器。 (不存在调用保留低位部分但不保留高位字节的调用约定,并且保存/恢复完整寄存器通常是最有效的。)
但如果您确实需要它,只需用 2 条指令来模拟它即可。
movzwl (%rsp), %ecx # or %r11d. implicitly zero-extends into the full 64-bit reg
add $2, %rsp # or if you need to preserve FLAGS,
# lea 2(%rsp), %rsp
pop 不存在零扩展形式; 8086 只能弹出全角(16 位)寄存器,因此没有现有的操作码需要修改。并且 386 没有引入任何与 movzx 或 movsx 等价的零扩展 pop;几乎没有人会从中受益:普通代码在使用时会使用全角推送/弹出。 (更常见的是当时常见的遗留堆栈参数调用约定,而不是前几个参数的现代高效寄存器参数。) 因此,不值得花费晶体管和操作码编码空间的成本。
或者,如果您不想零扩展,请pop %r11w
。 (不确定您是否不知道 r8..r15 的 low-8/low-16/low-32 寄存器的名称,或者为什么您在第二个示例中没有使用 RCX 来与 pop cx 进行对比)。
关于assembly - 如何将较小的值弹出到寄存器中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63651806/