汇编



拆弹过程中,遇到一条objdump给出的相当奇怪的指令:

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

我们知道那些常用的x86寄存器,那么,%eiz又是什么?

google了一下,除了google非常好心地询问我是不是想找%eip之外,相当多询问同样问题的人得到这样的解答:

%eiz是一个伪寄存器(pseudo-register ),总是读出0值,就像MIPS的R0那样。

好高级!寄存器都有伪的……

但是,之后就更加困惑了

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

从语义上来看就相当于:

lea 0x0(%esi),%esi

就又相当于:

lea (%esi),%esi

就相当于

mov %esi,%esi

也就是一句nop。

GCC又不是唐僧,为什么使用这种罗嗦的方式表达毫无意义的操作?实在想不明白……

继续google,翻了相当多老美的抱怨之后,一篇blog令我豁然开朗。

GCC在代码中插入nop是为了保证代码按照特定字节对齐,这个好理解。

nop只占一个字节,于是想对齐多少,GCC就插入多少nop。

后来有GCC的一些高玩发现,Intel CPU执行单条语句会比执行同功能的多条语句要快,嗯,即使是nop这样的无功能的语句。于是GCC开始把多条连续的nop替换成单条同样字节长度的无意义语句。

于是就有了那个奇怪写法的LEA。

太神奇了!

你可能感兴趣的:(汇编)