First save the "unsaved" registers if we will still care
about them after procedure returns
($t0, ..., $t9, $a0, ..., $a3
).
Where do they get saved?   the Stack (we'll talk about this in a minute)
$a0, ..., $a3
)
jal ProcedureAddress
) does 2 things:
$ra
. (Happens automatically.)
$ra
) to the Stack.
$s0
, ..., $s7
) to the
Stack.
$v0, $v1
).
$s0
, ...,
$s7
) and $ra
from the Stack.
$ra
(jr $ra
).jr
instruction jumps to an address stored in a register.
$v0, $v1
and retrieve any saved arguments and temporary registers
($a0, ..., $a3, $t0, ..., $t9
)
from the stack.
None of the register saves is automatic/guaranteed!!!
A big advantage of high-level languages is that compilers will always do this consistently and get it right.
# CODE STRUCTURE # (See next slide for info about "stack pointer".) caller: ... # push any A & T registers that you want saved to stack # put new arguments in $a0 - $a3 jal subFunc # pop any A & T registers that you saved # do stuff using value(s) in $v0, $v1 # do more stuff # return to "super-caller" or op. sys.
subFunc: # push $ra on stack if this is not a leaf function # push any S registers that will be used (if any) # body of subfunction (assume arguments are in $a0 - $a3) # (might include calls to other functions or this one) prepReturn: # put return value(s) in $v0, $v1 # pop all values that were pushed to stack jr $ra