a = a + 1;
lw $t0,12($fp) # get a addiu $t0,$t0,1 # a + 1 sw $t0,12($fp) # a =
When a subroutine is called, its stack frame is pushed onto the stack. And, when a subroutine returns to its caller its stack frame is popped. Pushing a stack frame is done by individually pushing the many full-words that it contains. And popping is done by individually popping each full-word in reverse order.
A real-world linkage convention allows many types of objects to go into a stack frame. The following rules assume that the stack stores only 32-bit values. There are other features of real-world linkage that the following does not have.
Subroutine Prolog (at the start of a subroutine):
Subroutine Body:
- Push
$ra(always).- Push the caller's frame pointer
$fp.- Push any of the registers
$s0-$s7that the subroutine might alter.- Initialize the frame pointer:
$fp = $sp - space_for_variables. The "space for variables" is four times the number of local variables.
(Remember that subtracting from$spgrows the stack, and that our variables are always four bytes wide).- Initialize the stack pointer:
$sp = $fp.
- At this point the stack looks like the picture.
The stack frame and its variables are ready for use.- The subroutine may alter any
T,A, orVregister, or anySregister that it saved in the prolog.- The subroutine refers to local variables as
disp($fp).- The subroutine may push and pop values on the stack using
$sp.- If the subroutine calls another subroutine, then it does so by following these rules.
Subroutine Call: (done by the caller, which might itself be a subroutine):
- Push any registers
$t0-$t9that contain values that must be saved. Push the registers in numerical order.- Put argument values into
$a0-$a3.- Call the subroutine using
jal.
Regaining Control: from a Subroutine call (done by the caller):
- Pop any registers
$t0-$t9that this caller pushed in step 11.
Subroutine Epilog: (at the end of the subroutine):
- Put return values in
$v0-$v1$sp = $fp + space_for_variables.
Now$sppoints at the lastSregister that was pushed in the prolog.- Pop into
$s0-$s7any values for them that were previously saved by the prolog (in step 3).- Pop the caller's frame pointer into
$fp.- Pop
$ra.- Return to the caller using
jr $ra.
Each push in the prolog (steps 1, 2, 3) is matched with a pop in the epilog (steps 17, 18, 19).
When a caller gets control back from a subroutine it called its frame pointer and stack pointer are the same as before it called the subroutine.
Why might a subroutine push and pop values on the stack
using $sp? (step 9)