Search code examples
cdisassemblycalling-convention

Why does `main` end with `ret` and not `ret 4`?


Consider the following empty C program (the standard guarantees that the compiler does an implicit return 0):

int main(int argc, char* argv[]) {}

You can add any logic into this function that manipulates argc and argv. Yet, when main finishes, its assembly code will just do a simple ret instead of ret 4. I am expecting to see a ret 4 because in my mind main is the callee of some other function and therefore must clean up its two arguments from the stack: and int and a pointer to char array. Why does it not do so?


Solution

  • Most compilers choose to have the caller clean the arguments from the stack; a tradition that dates from early C compilers and handling number of arguments. At the call-site, the compiler knows how many it pushed, so it is trivial for it to adjust the stack.

    Also, note that historically main can be specified with 0-3 (arge) arguments. Again, the caller (eg. _start) can just provide 3 and let the implementor choose.