我正在编译以下简单的演示函数:
int add(int a, int b) {
return a + b;
}这个函数自然是内联的,但让我们假设它是动态链接的,或者由于其他原因没有内联。禁用优化后,编译器会生成预期的代码:
00000000 <add>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 8b 45 0c mov eax,DWORD PTR [ebp+0xc]
6: 03 45 08 add eax,DWORD PTR [ebp+0x8]
9: 5d pop ebp
a: c3 ret由于此函数内部没有函数调用,因此0、1和9处的指令似乎没有任何用途。由于禁用了优化,因此这是可以接受的。
但是,在使用-Os -s优化大小的同时进行编译时,会生成完全相同的代码。使用这些选项将函数大小增加66%似乎是相当浪费的。
为什么代码没有针对以下方面进行优化?
00000000 <add>:
0: 8b 45 0c mov eax,DWORD PTR [esp+0x8]
3: 03 45 08 add eax,DWORD PTR [esp+0x4]
6: c3 ret编译器是否认为这不值得优化,或者这与函数对齐等其他细节有关?
发布于 2013-07-03 04:41:14
这样做是为了保留调试器单步执行代码的能力。
如果您确实想禁用此功能,请尝试使用-fomit-frame-pointer。
使用-Os -fomit-frame-pointer -S -masm=intel编译上面的代码会得到以下结果:
.file "frame.c"
.intel_syntax noprefix
.text
.globl _add
.def _add; .scl 2; .type 32; .endef
_add:
mov eax, DWORD PTR [esp+8]
add eax, DWORD PTR [esp+4]
ret
.ident "GCC: (rev0, Built by MinGW-builds project) 4.8.0"发布于 2013-07-03 04:49:36
代码可以使用mov eax,dword ptr [esp+8],而不用担心BP寄存器,但许多调试工具都假定每个局部变量相对于某个寄存器的偏移量是固定的。即使编译器可以跟踪推送到堆栈上的内容并适当地调整索引偏移量,调试器也很可能无法做到这一点。
https://stackoverflow.com/questions/17435446
复制相似问题