I accidentally discovered some strange thing about -fomit-frame-pointer from GCC to x86 when I was doing homework.
Take a look at the following code (which seems pretty clumsy, but somehow related to how I found the problem)
#include <stdio.h> void foo(void); int main() { foo(); return 0; } void foo() { printf("0x%x\n", *(unsigned char *)main); }
when compiling with the -m64 -O1 flag (-fomit-frame-pointer enabled) the disassembly looks like this
0000000000400500 <foo>: 400500: 48 83 ec 08 sub $0x8,%rsp 400504: 0f b6 35 14 00 00 00 movzbl 0x14(%rip),%esi # 40051f <main> 40050b: bf c4 05 40 00 mov $0x4005c4,%edi 400510: b8 00 00 00 00 mov $0x0,%eax 400515: e8 c6 fe ff ff callq 4003e0 < printf@plt > 40051a: 48 83 c4 08 add $0x8,%rsp 40051e: c3 retq 000000000040051f <main>: 40051f: 48 83 ec 08 sub $0x8,%rsp 400523: e8 d8 ff ff ff callq 400500 <foo> 400528: b8 00 00 00 00 mov $0x0,%eax 40052d: 48 83 c4 08 add $0x8,%rsp 400531: c3 retq
Everything looks great because% rbp is not displayed at all. However, when the code is compiled with the -m32 -O1 flag (starting with gcc 4.6, -fomit-frame-pointer becomes the default, and my is GCC 4.8.2) or even explicitly uses -fomit-frame-pointer , the disassembly looks like this.
08048400 <foo>: 8048400: 83 ec 1c sub $0x1c,%esp 8048403: 0f b6 05 1e 84 04 08 movzbl 0x804841e,%eax 804840a: 89 44 24 04 mov %eax,0x4(%esp) 804840e: c7 04 24 c0 84 04 08 movl $0x80484c0,(%esp) 8048415: e8 b6 fe ff ff call 80482d0 < printf@plt > 804841a: 83 c4 1c add $0x1c,%esp 804841d: c3 ret 0804841e <main>: 804841e: 55 push %ebp 804841f: 89 e5 mov %esp,%ebp 8048421: 83 e4 f0 and $0xfffffff0,%esp 8048424: e8 d7 ff ff ff call 8048400 <foo> 8048429: b8 00 00 00 00 mov $0x0,%eax 804842e: c9 leave 804842f: c3 ret
The foo function looks approximately the same in 32-bit and 64-bit versions. However, unlike the 64-bit one, the first two commands are main (note that it was compiled with -fomit-frame-pointer):
push %ebp mov %esp, %ebp
which resembles regular x86 code.
After several experiments, I found that if main calls another function, the code will look like the one mentioned above, and if main does not have a function call, the code will look like 64-bit.
I know this question may seem strange, but I'm just wondering why this difference exists between x86 and x86_64 code and exists only with main() function.