每当我在启用优化的情况下编译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。
函数填充字节有意义吗?
发布于 2010-12-20 10:42:21
填充是由组装者创建的,而不是由gcc创建的。它只看到一个.align指令(或等效指令),并不知道要填充的空间是在函数内部(例如循环对齐)还是函数之间,因此它必须插入某种类型的NOP。现代x86汇编器使用尽可能大的NOP操作码,目的是在填充用于循环对齐的情况下花费尽可能少的周期。
就我个人而言,我非常怀疑对齐作为一种优化技术。我从来没有见过它有多大的帮助,而且它肯定会因为极大地增加总代码大小(和缓存利用率)而受到伤害。如果您使用-Os优化级别,那么默认情况下它是关闭的,所以没有什么需要担心的。否则,您可以使用适当的-f选项禁用所有路线。
发布于 2010-12-20 10:04:17
指令lea 0x0(%esi),%esi只是将%esi中的值加载到%esi中-它是无操作(或NOP),这意味着如果它被执行,它将不起作用。
这恰好是一条单指令,6字节NOP。8d 74 26 00只是同一指令的4字节编码。
发布于 2011-09-10 00:42:30
汇编器首先看到一条.align指令。因为它不知道这个地址是否在函数体中,所以它不能输出空的0x00字节,而必须生成NOP (0x90)。
但是:
lea esi,[esi+0x0] ; does nothing, psuedocode: ESI = ESI + 0执行所需的时钟周期少于
nop
nop
nop
nop
nop
nop如果这段代码碰巧落在函数体中(例如,循环对齐),那么lea版本会快得多,同时仍然“什么都不做”。
https://stackoverflow.com/questions/4486301
复制相似问题