什么是注册%eiz?

时间:2010-03-31 13:57:55

标签: assembly x86 gas objdump

在我使用objdump转出的以下汇编代码中:

lea    0x0(%esi,%eiz,1),%esi

什么是注册%eiz?前面的代码是什么意思?

3 个答案:

答案 0 :(得分:54)

请参阅Why Does GCC LEA EIZ?

  

显然%eiz是一个伪寄存器,它在任何时候都只评估为零(如MIPS上的r0)。

...

  

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

答案 1 :(得分:23)

(游戏很晚,但这似乎是一个有趣的补充):它根本不是一个注册,它是英特尔指令编码的一个怪癖。当使用ModRM字节从存储器加载时,寄存器字段有3位用于存储8个可能的寄存器。但是,ESP(堆栈指针)“将”所在的位置被处理器解释为“SIB字节遵循该指令”(即,它是扩展寻址模式,而不是对ESP的引用)。由于作者只知道的原因,GNU汇编器总是将“零寄存器本来就是零”表示为“%eiz”寄存器。英特尔语法只是放弃了它。

答案 2 :(得分:14)

Andy Ross提供了更多潜在的推理,但不幸的是错误或至少混淆了技术细节。确实,只有(%esp)的有效地址不能仅用ModR / M字节编码,而不是被解码为(%esp),它用于表示还包括SIB字节。但是,%eiz伪寄存器并不总是与SIB字节一起使用来表示使用了SIB字节。

SIB字节(比例/索引/基数)有三个部分:索引(比例应用于%eax%ecx的寄存器),比例(a索引寄存器乘以1到2的2的幂,以及基数(添加到缩放索引的另一个寄存器)。这允许使用add %al,(%ebx,%ecx,2)(机器代码:00 04 4b - 操作码,modr / m,sib(即使使用了SIB字节也注意没有%eiz寄存器))(或在英特尔中)语法,“添加BYTE PTR [ecx * 2 + ebx],al”)。

但是,%esp不能用作SIB字节中的索引寄存器。而不是允许这个选项,英特尔改为添加一个选项来使用基址寄存器,没有缩放或索引。因此,消除add %al,(%ecx)(机器代码:00 01 - 操作码,modr / m)和add %al,(%ecx)(机器代码:00 04 21 - 操作码,modr /的情况之间的歧义m,sib),替代使用了替代语法add %al,(%ecx,%eiz,1)(或者用于英特尔语法:add BYTE PTR [ecx+eiz*1],al)。

正如Sinan链接的文章所解释的那样,这个特定指令(lea 0x0(%esi,%eiz,1),%esi)仅用作多字节nop(相当于esi = &*esi),因此只有一条nop式指令必须执行而不是多个nop指令。