什么是寄存器%eiz?
在我使用 objdump
转储出来的以下汇编代码中:
lea 0x0(%esi,%eiz,1),%esi
什么是寄存器 %eiz
?前面的代码是什么意思?
In the following assembly code that I dumped out using objdump
:
lea 0x0(%esi,%eiz,1),%esi
What is register %eiz
? What does the preceding code mean?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
请参阅 为什么 GCC LEA EIZ ?:
...
See Why Does GCC LEA EIZ?:
...
(游戏已经很晚了,但这似乎是一个有趣的补充):它根本不是寄存器,而是英特尔指令编码的一个怪癖。当使用 ModRM 字节从内存加载时,寄存器字段使用 3 位来存储 8 个可能的寄存器。但是 ESP(堆栈指针)“应该”所在的位置被处理器解释为“该指令后面有一个 SIB 字节”(即,它是扩展寻址模式,而不是对 ESP 的引用)。由于只有作者知道的原因,GNU 汇编器始终将这个“寄存器本来应该是的零”表示为“%eiz”寄存器。英特尔语法只是删除了它。
(Very late to the game, but this seemed like an interesting addition): It's not a register at all, it's a quirk of the Intel instruction encoding. When using a ModRM byte to load from memory, there are 3 bits used for the register field to store 8 possible registers. But the spot where ESP (the stack pointer) "would" be is instead interpreted by the processor as "a SIB byte follows this instruction" (i.e. it's an extended addressing mode, not a reference to ESP). For reasons known only to the authors, the GNU assembler has always represented this "zero where a register would otherwise be" as a "%eiz" register. The Intel syntax just drops it.
安迪·罗斯提供了更多的基本推理,但不幸的是错误的,或者至少在技术细节上令人困惑。确实,仅
(%esp)
的有效地址不能仅使用 ModR/M 字节进行编码,而不是解码为(%esp)
,而是用于表示还包含 SIB 字节。然而,%eiz
伪寄存器并不总是与 SIB 字节一起使用来表示已使用 SIB 字节。SIB 字节 (scale/index/base) 包含三个部分: 索引(应用缩放的寄存器,例如
%eax
或%ecx
) 、标度(索引寄存器乘以 1 到 8 的 2 的幂)和基址(添加到缩放索引的另一个寄存器)。这就是允许诸如add %al,(%ebx,%ecx,2)
之类的指令(机器代码:00 04 4b
-- 操作码、modr/m、 sib(注意,即使使用了 SIB 字节,也没有 %eiz 寄存器))(或者在 Intel 语法中,“add BYTE PTR [ecx*2+ebx], al”)。但是,
%esp
不能用作 SIB 字节中的索引寄存器。英特尔没有允许此选项,而是添加了一个按原样使用基址寄存器的选项,没有缩放或索引。因此,要消除add %al,(%ecx)
(机器代码:00 01
-- opcode, modr/m)和add %al 的情况之间的歧义,(%ecx)
(机器代码:00 04 21
-- 操作码、modr/m、sib),替代语法add %al,(%ecx,%eiz ,1)
被改用(或者对于 Intel 语法:add BYTE PTR [ecx+eiz*1],al
)。正如 Sinan 链接的文章中所解释的,这条特定指令 (
lea 0x0(%esi,%eiz,1),%esi
) 仅用作多字节 nop(相当于 < code>esi = &*esi),这样只需执行一条类似 nop 的指令,而不是执行多条 nop 指令。Andy Ross provides a lot more of the underlying reasoning, but is unfortunately wrong or at the very least confusing about the technical details. It is true that an effective address of just
(%esp)
cannot be encoded with just the ModR/M byte as instead of being decoded as(%esp)
, it is used to signal that a SIB byte is also included. However, the%eiz
pseudo-register is not always used with a SIB byte to represent that a SIB byte was used.The SIB byte (scale/index/base) has three pieces to it: the index (a register such as as
%eax
or%ecx
that the scale is applied to), the scale (a power of two from 1 to 8 that the index register is multiplied by), and the base (another register that is added to the scaled index). This is what allows for instructions such asadd %al,(%ebx,%ecx,2)
(machine code:00 04 4b
-- opcode, modr/m, sib (note no %eiz register even though the SIB byte was used)) (or in Intel syntax, "add BYTE PTR [ecx*2+ebx], al").However,
%esp
cannot be used as the index register in a SIB byte. Instead of allowing this option, Intel instead adds an option to use the base register as is with no scaling or indexing. Therefore to disambiguate between the case ofadd %al,(%ecx)
(machine code:00 01
-- opcode, modr/m) andadd %al,(%ecx)
(machine code:00 04 21
-- opcode, modr/m, sib), the alternate syntaxadd %al,(%ecx,%eiz,1)
is instead used (or for Intel syntax:add BYTE PTR [ecx+eiz*1],al
).And as explained in the article linked to by Sinan, this specific instruction (
lea 0x0(%esi,%eiz,1),%esi
) is merely used as a multi-byte nop (equivalent toesi = &*esi
) so that only one nop-like instruction has to be executed instead of multiple nop instructions.