I was debugging a simple x86-64 program in Visual Studio 2010 and I noticed that the main
function preamble is different from the GNU GCC compiled version of the same C program.
To illustrate what I mean here is the C code for the main
function:
int main() {
int a,b,c;
a=1;
b=2;
c=proc(a,b);
return c;
}
The Visual Studio 2010 disassembly of the main
function preamble for the VC++ version is:
01211410 push ebp
01211411 mov ebp,esp
01211413 sub esp,0E4h
01211419 push ebx
0121141A push esi
0121141B push edi
0121141C lea edi,[ebp-0E4h]
01211422 mov ecx,39h
01211427 mov eax,0CCCCCCCCh
0121142C rep stos dword ptr es:[edi]
The rest of the function code of the VC++ version is:
0081141E mov dword ptr [a],1
00811425 mov dword ptr [b],2
0081142C mov eax,dword ptr [b]
0081142F push eax
00811430 mov ecx,dword ptr [a]
00811433 push ecx
00811434 call proc (81114Fh)
00811439 add esp,8
0081143C mov dword ptr [c],eax
0081143F mov eax,dword ptr [c]
00811442 pop edi
00811443 pop esi
00811444 pop ebx
00811445 add esp,0E4h
0081144B cmp ebp,esp
0081144D call @ILT+300(__RTC_CheckEsp) (811131h)
00811452 mov esp,ebp
00811454 pop ebp
00811455 ret
The disassembly of the main
function preamble for the GCC compiled version is:
00400502 push rbp
00400503 mov rbp,rsp
00400506 sub rsp,0x10
The rest of the main
function code of the GCC version is:
004004e8 mov DWORD PTR [rbp-0xc],0x1
004004ef mov DWORD PTR [rbp-0x8],0x2
004004f6 mov edx,DWORD PTR [rbp-0x8]
004004f9 mov eax,DWORD PTR [rbp-0xc]
004004fc mov esi,edx
004004fe mov edi,eax
00400500 call 0x4004cc <proc>
00400505 mov DWORD PTR [rbp-0x4],eax
00400508 mov eax,DWORD PTR [rbp-0x4]
0040050b leave
0040050c ret
The same disassembly is given by objdump
version 2.22.90.20120924.
I realize that the first 3 instructions for both preambles do the following:
- Save old EBP (later needed to remove stack frame)
- Top of old stack frame becomes EBP of new frame
- Reserve space for local variables. The function has 3 integer local variables.
Question 1: What is the purpose of 4th instruction in the VC++ version? I see its saving EBX, but why? It never uses it afterwards.
For the remaining instructions of the VC++ version preamble, I relized that it initializes 39h
dwords with the value 0CCCCCCCCh
. Which makes sense because 39h * 4h = 0E4h
.
Question 2: Why is this space initialized with the value 0CCCCCCCCh
? Is this value better than 00000000h
in some way?
Question 3: Why does the VC++ version allocate 0E4h
bytes for 3 local variables? Is this number random? If not, how is it computed?
Question 4: Is this space used for something else beside local variables? If yes, for what?
0
, not the value ofc
...