This section summarizes important points of the convention used for normal function calls on 32-bit 80x86 implementations of Unix. Some details are omitted for brevity.
The calling convention works like this:
The caller pushes each of the function’s arguments on the stack one by one, normally using the
Arguments are pushed in right-to-left order. The stack grows downward: each push decrements the stack pointer, then stores into the location it now points to, like the C expression
*(--sp) = value.
- The caller pushes the address of its next instruction (the return address) on the stack and jumps to the first instruction of the callee. A single 80x86 instruction,
call, does both.
- The callee executes. When it takes control, the stack pointer points to the return address, the first argument is just above it, the second argument is just above the first argument, and so on.
- If the callee has a return value, it stores it into register
- The callee returns by popping the return address from the stack and jumping to the location it specifies, using the 80x86
- The caller pops the arguments off the stack.
Consider a function
f() that takes three int arguments. This diagram shows a sample stack frame as seen by the callee at the beginning of step 3 above, supposing that
f() is invoked as
f(1, 2, 3). The initial stack address is arbitrary:
+----------------+ 0xbffffe7c | 3 | 0xbffffe78 | 2 | 0xbffffe74 | 1 | stack pointer --> 0xbffffe70 | return address | +----------------+