GCC 生成无用的指令?
GCC generates useless instructions?
BOOL32 doStuff() {
return TRUE;
}
gcc 2.95 for vxworks 5.x,使用 -O0
为 32 位 x86 编译以上代码生成以下代码:
doStuff:
0e9de190: push %ebp
0e9de191: mov %esp,%ebp
308 return TRUE;
0e9de193: mov [=11=]x1,%eax
0e9de198: jmp 0xe9de1a0 <doStuff+16>
312 {
0e9de19a: lea 0x0(%esi),%esi
// The JMP jumps here
0e9de1a0: mov %ebp,%esp
0e9de1a2: pop %ebp
0e9de1a3: ret
在 JMP 和 LEA 指令之前,一切看起来都很正常。它们有什么用?
我猜这是某种对齐方式,但我不确定。
我会做这样的事情:
doStuff:
0e9de190: push %ebp
0e9de191: mov %esp,%ebp
308 return TRUE;
0e9de193: mov [=12=]x1,%eax
0e9de1XX: mov %ebp,%esp
0e9de1XX: pop %ebp
0e9de1XX: ret
0e9de1XX: fill with lea 0x0, %esi
lea 0x0(%esi),%esi
是一个long NOP,jmp就是跳过了。您可能有一个 ancient 版本的 binutils(包含 as
)来配合您的旧 gcc 版本。
因此,当 gcc 放置一个 .p2align
以在函数中间对齐一个标签时,该标签不是分支目标(出于某些奇怪的原因,但它是 -O0,所以它甚至不应该是好的代码),汇编程序做了一个很长的 NOP 并跳过了它。
通常情况下,如果有很多 NOP,您只会跳过一块 NOP,尤其是当它们都是单字节 NOP 时。这真是愚蠢的代码,所以停止使用这种硬壳工具。您可以尝试升级您的汇编程序(但如果需要,仍然使用 gcc2.95)。或者检查它是否不会发生在 -O2
或 -O3
,在这种情况下无关紧要。
如果您出于某种原因必须继续使用 gcc2.95,请注意它是古老的,这是您为继续使用迫使您使用它的任何东西而做出的权衡的一部分。
BOOL32 doStuff() {
return TRUE;
}
gcc 2.95 for vxworks 5.x,使用 -O0
为 32 位 x86 编译以上代码生成以下代码:
doStuff:
0e9de190: push %ebp
0e9de191: mov %esp,%ebp
308 return TRUE;
0e9de193: mov [=11=]x1,%eax
0e9de198: jmp 0xe9de1a0 <doStuff+16>
312 {
0e9de19a: lea 0x0(%esi),%esi
// The JMP jumps here
0e9de1a0: mov %ebp,%esp
0e9de1a2: pop %ebp
0e9de1a3: ret
在 JMP 和 LEA 指令之前,一切看起来都很正常。它们有什么用?
我猜这是某种对齐方式,但我不确定。
我会做这样的事情:
doStuff:
0e9de190: push %ebp
0e9de191: mov %esp,%ebp
308 return TRUE;
0e9de193: mov [=12=]x1,%eax
0e9de1XX: mov %ebp,%esp
0e9de1XX: pop %ebp
0e9de1XX: ret
0e9de1XX: fill with lea 0x0, %esi
lea 0x0(%esi),%esi
是一个long NOP,jmp就是跳过了。您可能有一个 ancient 版本的 binutils(包含 as
)来配合您的旧 gcc 版本。
因此,当 gcc 放置一个 .p2align
以在函数中间对齐一个标签时,该标签不是分支目标(出于某些奇怪的原因,但它是 -O0,所以它甚至不应该是好的代码),汇编程序做了一个很长的 NOP 并跳过了它。
通常情况下,如果有很多 NOP,您只会跳过一块 NOP,尤其是当它们都是单字节 NOP 时。这真是愚蠢的代码,所以停止使用这种硬壳工具。您可以尝试升级您的汇编程序(但如果需要,仍然使用 gcc2.95)。或者检查它是否不会发生在 -O2
或 -O3
,在这种情况下无关紧要。
如果您出于某种原因必须继续使用 gcc2.95,请注意它是古老的,这是您为继续使用迫使您使用它的任何东西而做出的权衡的一部分。