【问题标题】:Understanding the pop instruction in assembly理解汇编中的pop指令
【发布时间】:2018-09-16 17:05:03
【问题描述】:

我是第一次学习计算机系统的学生(w/ Computer Systems: A Programmer's Perspective)。我们正在组装,我开始了解 x86_64 的命令后缀,例如使用 leaq 如下:

leaq (%rsp, %rdx), %rax

但是,我无法理解为 pop 使用后缀。例如,使用相同的逻辑,对我来说,我们将 popl 用于以下内容是有意义的:

popl %edi

但是,在网上的文字和其他例子中,我只是看到:

pop %edi

有什么区别? popl 是否有效?只是寻找更多的见解。有什么帮助,谢谢。

【问题讨论】:

  • 无效。请参阅指令集参考以查看允许的形式。如果可以从参数中推断出大小,则可以省略后缀。 lea (%rsp, %rdx), %rax(不带后缀)有效且是同一条指令。 popq %rdipop %rdi 也是有效的。 pop %edi 在 64 位代码、后缀或无后缀中根本无效。

标签: gcc assembly x86-64 inline-assembly


【解决方案1】:

您在 asm 中可以做的事情受到硬件可以做的事情的限制。源代码中的隐式与显式操作数大小(后缀与否)不会更改它将汇编到的机器代码。

所以要问的正确问题是硬件是否可以在 64 位模式下进行 32 位推送?不,它不能,因此不存在 asm 源语法可以让它完全按照您尝试使用一条指令执行的操作。

这就是你的汇编器不接受pop %edipopl %edi 的原因。这些是完全等价的,因为 32 位寄存器意味着 DWORD (l) 操作数大小。 您看到的 poplpop %edi 的示例是针对 32 位模式的,其中 EDI 是完整的寄存器而不是 RDI 的低半部分,并且该指令是可编码的。

只有在大小不明确时才需要大小后缀,mov $1, (%rdi)。您的汇编程序会为此给出错误,而不是猜测 b/w/l/q 之一。

但推送有点特殊:push $1 将默认为 64 位推送,即使 pushw $1 是可能的。 How many bytes does the push instruction push onto the stack when I don't specify the operand size?

【讨论】:

  • 你可能想解释一下,在 32 位和 16 位模式下,push r32 当然是可以的。
猜你喜欢
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-19
  • 2011-05-03
相关资源
最近更新 更多