Function-call stack frame
When the compiler generates code for a
function call, it first pushes all the arguments on the stack, then makes the
call. Inside the function, code is generated to move the stack pointer down even
farther to provide storage for the function’s local variables.
(“Down” is relative here; your machine may increment or decrement
the stack pointer during a push.) But during the assembly-language
CALL, the CPU pushes the address
in the program code where the function call came from, so the
assembly-language RETURN can use
that address to return to the calling point. This address is of course sacred,
because without it your program will get completely lost. Here’s what the
stack frame looks like after the CALL and the allocation of local variable
storage in the function:
The code generated for the rest of the
function expects the memory to be laid out exactly this way, so that it can
carefully pick from the function arguments and local variables without touching
the return address. I shall call this block of memory, which is everything used
by a function in the process of the function call, the function
frame.
You might think it reasonable to try to
return values on the stack. The compiler could simply push it, and the function
could return an offset to indicate how far down in the stack the return value
begins.