GCC功能填充值

时间:2010-12-20 01:45:51

标签: c++ c gcc

每当我使用优化启用编译C或C ++代码时,d GCC将函数对齐到16字节边界(在IA-32上)。如果函数短于16个字节,GCC会用一些字节填充它,这看起来根本不是随机的:

19:   c3                      ret
1a:   8d b6 00 00 00 00       lea    0x0(%esi),%esi

它似乎总是8d b6 00 00 00 00 ...8d 74 26 00

函数填充字节有什么意义吗?

3 个答案:

答案 0 :(得分:7)

填充由汇编程序创建,而不是由gcc创建。它只是看到.align指令(或等价物)并且不知道要填充的空间是在函数内部(例如循环对齐)还是在函数之间,因此它必须插入一些NOP s分类。现代x86汇编程序使用尽可能大的NOP操作码,如果填充用于循环对齐,则意图花费尽可能少的周期。

就个人而言,我对作为优化技术的对齐持怀疑态度。我从来没有看到它有多大帮助,并且通过极大地增加总代码大小(和缓存利用率)肯定会受到伤害。如果您使用-Os优化级别,默认情况下它已关闭,因此无需担心。否则,您可以使用正确的-f选项停用所有路线。

答案 1 :(得分:2)

指令lea 0x0(%esi),%esi只是将%esi中的值加载到%esi - 它是无操作(或NOP),这意味着如果它被执行它将没有效果。

这恰好是单指令,6字节NOP。 8d 74 26 00只是同一指令的4字节编码。

答案 2 :(得分:2)

汇编程序首先看到.align指令。由于它不知道该地址是否在函数体内,因此它不能输出NULL 0x00个字节,并且必须生成NOP s(0x90)。

然而:

lea    esi,[esi+0x0] ; does nothing, psuedocode: ESI = ESI + 0

执行的时钟周期比

nop
nop
nop
nop
nop
nop

如果此代码恰好位于函数体内(例如,循环对齐),lea版本会更快,但仍然“无所事事。”