This isn t really a C question since it s totally dependent on the compiler.
However stack frames are a useful way to think about the current function and it s parent function. Typically a frame pointer points to a specific location on the stack (for the given stack depth) from which you can locate parameters that were passed in as well as local variables.
Here s an example, let s say you call a function which takes one argument and returns the sum of all numbers between 1 and that argument. The C code would be something like:
unsigned int x = sumOf (7);
: :
unsigned int sumOf (unsigned int n) {
unsigned int total = 0;
while (n > 0) {
total += n;
n--;
}
return total;
}
In order to call this function, the caller will push 7 onto the stack then call the subroutine. The function itself sets up the frame pointer and allocates space for local variables, so you may see the code:
mov r1,7 ; fixed value
push r1 ; push it for subroutine
call sumOf ; then call
retLoc: mov [x],r1 ; move return value to variable
: :
sumOf: mov fp,sp ; Set frame pointer to known location
sub sp,4 ; Allocate space for total.
: :
At that point (following the sub sp,4
), you have the following stack area:
+--------+
| n(7) |
+--------+
| retLoc |
+--------+
fp -> | total |
+--------+
sp -> | |
+--------+
and you can see that you can find passed-in parameters by using addresses above the frame pointer and local variables below the frame pointer.
The function can access the passed in value (7) by using [fp+8]
, the contents of memory at fp+8
(each of those cells is four bytes in this example). It can also access its own local variable (total
) with [fp-0]
, the contents of memory at fp-0
. I ve used the fp-0
nomenclature even though subtracting zero has no effect since other locals will have corresponding lower addresses like fp-4
, fp-8
and so on.
As you move up and down the stack, the frame pointer also moves and it s typical that the previous frame pointer is pushed onto the stack before calling a function, to give easy recovery when leaving that function. But, whereas the stack pointer may move wildly while within a function, the frame pointer typically stays constant so you can always find your relevant variables.