I accidentally discovered some strange thing about the -fomit-frame-pointer with GCC on x86 when I was doing homework.
Look at the following code (which seems quite nonsense but somehow related to how I discovered the problem)
#include <stdio.h>
void foo(void);
int main()
{
foo();
return 0;
}
void foo()
{
printf("0x%x\n", *(unsigned char *)main);
}
when compiled with -m64 -O1 flag (-fomit-frame-pointer enabled), the disassembly is like the following
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 fine because %rbp does not show up at all. However when the code is compiled with -m32 -O1 flag (starting from gcc 4.6 -fomit-frame-pointer becomes default and mine is GCC 4.8.2) or even use -fomit-frame-pointer explicitly, the disassembly is like the following.
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 function foo looks quite the same in 32 bit and 64 bit. However, unlike the 64-bit one, the first two instructions of main are (notice that it is compiled with -fomit-frame-pointer):
push %ebp
mov %esp, %ebp
which resembles normal x86 code.
After several experiments I found that if main calls another function, the code will be like the one above, and if there is no function call in main, the code will resembles the 64-bit ones.
I know this question may seem strange but I'm just curious about why this difference exists between x86 and x86_64 code, and only exists with main() function.