views:

173

answers:

2

Hello,

I just noticed some strange assembly language code of empty main method.

//filename: main.c
void main()
{

}

disassembly:

push        ebp  
mov         ebp,esp  
sub         esp,0C0h; why on the earth is it reserving 192 bytes?  
push        ebx  
push        esi  
push        edi  ; good compiler. Its saving ebx, esi & edi values.
lea         edi,[ebp-0C0h]  ; line 1
mov         ecx,30h  ; line 2
mov         eax,0CCCCCCCCh  ; line 3
rep stos    dword ptr es:[edi]  ; line 4


xor         eax,eax  ; returning value 0. Code following this line is explanatory.
pop         edi  ; restoring the original states of edi,esi & ebx
pop         esi  
pop         ebx  
mov         esp,ebp  
pop         ebp  
ret   
  1. why on the earth is it reserving 192 bytes for function where there aren't any variables
  2. whats up with the four lines: line 1, line 2, line 3, line 4? what is it trying to do & WHY?
+14  A: 

The four code lines you've indicated are the debug build clearing out the local variable space with the "clear" special value (0xCCCCCCCC).

I'm not sure why there are 192 bytes of seemingly dead space, but that might be VC++ building some guard space into your local variable area to try to detect stack smashing.

You will probably get a very different output if you switch from Debug to Release build.

Greg Hewgill
why `0xCCCCCCCC`=`1100 1100 1100 1100 1100 1100 1100 1100`? wouldn't clearing out with 0x00000000 would be more meaningful?
claws
@claws: Microsoft chose that value because it's distinct and easy to identify if your program ends up using an uninitialised variable. Using zero would mask a lot of potential bugs because often variables would be initialised to zero anyway, and having the compiler do so in a debug build would cause the release build to fail.
Greg Hewgill
@Greg Hewgill: How to view disassembly in Release configuration in Visual Studio? I was putting a breakpoint at the closing bracket and viewing disassembly. This doesn't seem to work in release mode.
claws
@claws: You can enable debug info (so you can see the disassembly) while still leaving all the other settings as they are for Release mode. I'm not sure exactly where the knob is on your version of VS, but it's on the project properties page somewhere.
Greg Hewgill
@Greg Hewgill: Are you referring to "Program Database for Edit And Continue (/ZI)" option for "Program Database Format"?Because thats already enabled. Actually, In release mode. I'm able to set breakpoints and its even showing the disassembly looks like this: http://pastebin.com/raw.php?i=YnjjgnnL . Why is it so?
claws
@claws: Your pastebin is precisely what I would expect for a release mode build of an empty function that returns 0. As I said, you'll get very different output when the compiler doesn't emit any code that's unnecessary.
Greg Hewgill
@Greg Hewgill: Ah yes, I remember it well. In fact, once this uninitialised pattern caused us a huge problem when a bug was reported by a customer that only occurred in the release build, we could not reproduce it at all. It turned out that we were using a boolean uninitialised. In the release build it was often zero, but in the debug build it never was. It's a far better idea to turn on the warning about use of uninitialised variables.
JeremyP
The term for the "special value" is memory poison.
Matt Joiner
+9  A: 

Greg already explained how the compiler generates code to diagnose uninitialized local variables, enabled by the /RTCu compile option. The 0xcccccccc value was chosen to be distinctive and easily recognized in the debugger and to ensure the program bombs when an uninitialized pointer is dereferenced. The debug allocator initializes its memory to a similar value, 0xcdcdcdcd.

The mysterious 192 bytes that are allocated in the stack frame are there to support the Edit + Continue feature, /ZI compile option. It allows you to edit the code while a breakpoint is active. And add local variables to a function. Those 192 bytes are available to provide the space for those added locals. Exceeding that space with your edits will make the IDE rebuild your program, depending on the current execution address.

Btw: this can cause a problem if you use recursion in your code. The debug build will bomb on a stack overflow exception a lot quicker.

Hans Passant
Up, for offering info that's obscure but fascinating.
mickeyf