【发布时间】:2017-09-22 06:37:14
【问题描述】:
我发现 x86-64 程序(至少是那些使用 GCC 编译的程序)的函数默认从与 16 字节的倍数对齐的地址开始,并且填充是由带有 前缀的 NOP 指令完成的可以适合以最佳地填充空间。例如,
(...)
447454: c3 retq
447455: 90 nop
447456: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%rax,%rax,1)
0000000000447460 <__libc_csu_fini>:
447460: f3 c3 repz retq
【问题讨论】:
-
这些链接问题的答案似乎也适用于这里
-
@HongOoi 他们说为什么对齐很好,但没有说为什么
nopw %cs:0x0(%rax,%rax,1)比 10×nop好。实际上,这种可能性只提到过一次;所有的例子都只是重复nops 并且其中一个引号甚至说“对齐子例程条目就像根据需要放置 尽可能多的 NOP 一样简单......” -
将分支目标对齐到 16 的倍数是标准优化规则。它帮助指令解码器处理分支错误预测,它不必遍历未使用的指令。 REP 前缀是一个有助于 AMD 处理器的不稳定前缀,它避免了错误预测。顺便说一句,他们现在推荐 RET 0。处理器没有变得更容易编程;)
-
@HansPassant:
rep ret在 AMD Bulldozer 系列和 Ryzen 上比ret 0快。在英特尔 CPU 上也是如此。它们在 K8/K10 上的速度相同。所以这是一件好事gcc使用rep ret而不是ret 0在它仍然关心Athlon64 / PhenomII 的“通用”调整中。现在切换没有意义,因为rep ret存在于无处不在的二进制文件中(来自gcc的默认输出),因此几十年来没有CPU 供应商会重新利用该字节序列。 stackoverflow.com/questions/20526361/what-does-rep-ret-mean/…。ret 0最初会“更安全”。 -
处理器没有变得更容易编程这不是事实。
标签: gcc assembly x86 x86-64 micro-optimization