什么是寄存器%eiz?

发布于 2024-08-26 21:39:47 字数 146 浏览 16 评论 0原文

在我使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情丝乱 2024-09-02 21:39:47

请参阅 为什么 GCC LEA EIZ ?

显然 %eiz 是一个伪寄存器,其值始终为零(如 MIPS 上的 r0)。

...

我最终找到了 binutils 大师 Ian Lance Taylor 的邮件列表帖子,其中揭示了答案。有时,GCC 会在代码流中插入 NOP 指令,以确保正确对齐等。 NOP 指令占用一个字节,因此您可能会认为可以根据需要添加任意数量的字节。但根据 Ian Lance Taylor 的说法,芯片执行一条长指令比执行许多短指令要快。因此,他们没有插入 7 个 NOP 指令,而是使用一个奇怪的 LEA,它占用了 7 个字节,在语义上等同于 NOP。

See Why Does GCC LEA EIZ?:

Apparently %eiz is a pseudo-register that just evaluates to zero at all times (like r0 on MIPS).

...

I eventually found a mailing list post by binutils guru Ian Lance Taylor that reveals the answer. Sometimes GCC inserts NOP instructions into the code stream to ensure proper alignment and stuff like that. The NOP instruction takes one byte, so you would think that you could just add as many as needed. But according to Ian Lance Taylor, it’s faster for the chip to execute one long instruction than many short instructions. So rather than inserting seven NOP instructions, they instead use one bizarro LEA, which uses up seven bytes and is semantically equivalent to a NOP.

雪化雨蝶 2024-09-02 21:39:47

(游戏已经很晚了,但这似乎是一个有趣的补充):它根本不是寄存器,而是英特尔指令编码的一个怪癖。当使用 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.

羁〃客ぐ 2024-09-02 21:39:47

安迪·罗斯提供了更多的基本推理,但不幸的是错误的,或者至少在技术细节上令人困惑。确实,仅 (%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 as add %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 of add %al,(%ecx) (machine code: 00 01 -- opcode, modr/m) and add %al,(%ecx) (machine code: 00 04 21 -- opcode, modr/m, sib), the alternate syntax add %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 to esi = &*esi) so that only one nop-like instruction has to be executed instead of multiple nop instructions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文