Search code examples
linuxx86calling-convention

C calling conventions and passed arguments


When making a function call in Linux (or OS X for that matter), can the callee modify the values of the arguments on the stack? I was under the assumption that since the caller is the one that cleans them up, that they should contain the same values after the function call. However I found that GCC with -O2 was modifying parameters that were passed to it on the stack. I have also looked for documentation including the System V i386 calling conventions, but was unable to find a definitive answer to this.

Here is some sample code I was debugging.

pushl %eax       # %eax = 0x28
call _print_any
popl %eax
                 # %eax is now 0x0a

I would assume that GCC modifying that parameter on the stack is fine, but I want to know where it is specified that it can do so.


Solution

  • Although the caller (in some calling conventions) is the one that cleans up the arguments, all it's really doing is deallocating the space previously allocated on the stack to hold the argument values. The callee is free to modify the values during execution of the function, because the caller isn't going to look at their values later.

    In the example you posted, GCC has emitted the popl %eax instruction to deallocate the space taken by the parameter on the stack. All it really needs to do is add 4 to %esp (the stack on x86 grows downwards in memory), and executing the popl %eax instruction is the shortest and fastest way to do this. If the compiler needed to deallocate 20 values, it would probably modify %esp directly instead of emitting 20 popl instructions.

    You will probably find that the new value of %eax is not used in the following code.