(1) The stack frame is empty right before we call a function:
Initial state: the stack frame for the function call f( ) is empty
(2) The caller passes the parameters by pushing them on the stack:
The stack frame first contains the parameters of the function f( )
(3) The bl instruction will jump to the function:
The stack frame is unchanged
(4) The function f will save the the return address on the stack:
The stack frame now has parameters + return address
(5) The function f must also save the the base address in FP in the stack:
The stack frame now has parameters + return address + old FP
(6) The function f now safely establish the base address of the stack frame in FP
FP points to the "middle" of the (unfinished) stack frame
(7) The function f will create its local variables using the stack:
The stack frame now has parameters + return address + old FP + local variables
|
Previously we saw that a subroutine always begins with these 4 assembler instructions:
Using the sub instruction to allocate local variables:
The prelude code of a subroutine with parameters and local variables on stack:
push {lr} // Save return address push {fp} // Save caller's FP mov fp, sp // Set up base address in FP sub sp, sp, #n // Allocate n/4 int local variables |
The prelude code always appear as the first 4 assembler instruction in (non-leaf) subroutines that must uses the runtime stack to store their local variables and parameters
The stack frame is the data structure used to store the parameters and local variables of an active function
The stack frame always has the following structure:
The parameters and local variables are access using FP as base address
The figure gives the offsets that you need to use to access the parameters and local variables