I wrote a simple C++ code and compiled it in VS 2013. I am trying to understand what happen after return 0.

int main(){
    return 0;

The assembly code of return 0, translates to the xor eax, eax

011F1B19  xor         eax,eax  
011F1B1B  pop         ebp  
011F1B1C  ret  

After ret, it jumps to 011F121A

011F1203  push        dword ptr ds:[11F3034h]  
011F1209  push        dword ptr ds:[11F3030h]  
011F120F  push        dword ptr ds:[11F302Ch]  
011F1215  call        main (011F1B00h)  
011F121A  add         esp,0Ch  
011F121D  mov         dword ptr ds:[011F3024h],eax  
011F1222  cmp         dword ptr ds:[11F3028h],0
011F1229  jne         __tmainCRTStartup+144h (011F1261h)
#ifndef _CRT_APP
011F122B  push        eax  
011F122C  call        dword ptr ds:[11F2078h]  

I have two questions:

  1. Why does the return translates to xor eax, eax?

  2. Why does the function dereference ptr in ds segments at 011F121D and 011F1222 and 011F122C?

  • 1
    Your questions were answered below. But as an aside, if you want to remove the C runtime code from your executable, you can set the entry point to your main function (assuming you're not using any functions from the C runtime in your code). Apr 27, 2015 at 13:00

2 Answers 2

xor eax, eax

Is the fastest way to zero a register. You will see this everywhere on x86. All x86 ABIs specify that an integer return value is placed in the eax register.

ds is the default segment for most memory accesses. Your disassembler is just being explicit.

I'm not familiar with the specifics on Windows, but basically the C runtime stub compiled into your program will take the return value from main, and pass it to a system call to exit the process. (Returning from main is equivalent to calling exit.)

  • Incidentally, this is the proper way to exit under UNIX style environments as well. A syscall with the return code set either on the stack or in a register. May 2, 2015 at 2:43
  • @DavidHoelzer syscall arguments on x86 are always in registers. May 2, 2015 at 13:00
  • Yes, you are correct. I had the differences between cdecl, pascal and fastcall and functions in my head, but all user mode calls for system calls on x86 will be in registers. May 2, 2015 at 13:02

The xor reason is obvious. the return value. when using c++ in x86/64 land the return value of functions stores in EAX register before return. because you wrote "return 0" the value of eax must be 0:

opcode: b8 00 00 00 00 asm:mov eax, 0*

the optimizer make better choice:

opcode: 31 c0 asm: xor eax, eax

so the result is equal eax = 0 with optimization.

about the "011F3024h", since OS must take care of return value of each program, it must save your return address for later use. this is it ( for simple answer ) for more detailed answer read RE of __tmainCRTStartup


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.