如何将较小的值弹出到寄存器中

How to pop a lesser-sized value into a register

我有一个 2 字节的值存储在堆栈中,我想 pop 将它存入寄存器。我可以通过使用其中的 16 位寄存器在其中一个通用寄存器上执行此操作,例如:

popw %cx

有没有办法将它放入另一个寄存器,例如r11并用零填充它?类似于:

popzwq %r11   # making up the syntax

或者这样做的正确方法是什么?

通常你首先通过从不使用pushw来避免这种情况,而是在压入/弹出时总是使用full-width(64位)堆栈槽。那也保持堆栈对齐。此外,通常你只会在进入/离开函数时使用 push/pop 到 save/restore 寄存器。 (没有低位部分是 call-preserved 而不是高位字节的调用约定,通常 save/restore 完整寄存器最有效。)

但如果您确实需要它,只需用 2 条指令模拟它即可。

   movzwl  (%rsp), %ecx          # or %r11d.  implicitly zero-extends into the full 64-bit reg
   add     , %rsp              # or if you need to preserve FLAGS,
                                 # lea 2(%rsp), %rsp

没有 zero-extending 种流行形式; 8086 只能弹出 full-width(16 位)寄存器,因此没有要修改的现有操作码。 386 并没有引入任何 zero-extending 相当于 movzx 或 movsx 的 pop;几乎没有人会从中受益:普通代码在使用 full-width push/pop 时使用它。 (更常见于当时常见的遗留 stack-args 调用约定,而不是前几个参数的现代高效注册参数。) 所以不值得在晶体管和操作码编码上花费 space。


或者如果您不想 zero-extend,pop %r11w。 (不确定您是否不知道 r8..r15 的 low-8 / low-16 / low-32 寄存器的名称,或者为什么您没有在第二个示例中使用 RCX 来与 pop cx 进行对比)。