Place parameters in a place where the procedure can access them.
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)
Transfer control to the procedure.
jal ProcedureAddress) does 2 things:
$ra. (Happens automatically.)
Acquire the storage resources needed for the procedure.
$ra) to the Stack.
$s0, ..., $s7) to the
Stack.
Perform the desired task.
(May include calls to
other procedures or recursive calls to this procedure.)
Place the result values in a place where the calling program can access
them ($v0, $v1).
Release the storage resources needed for the procedure.
$s0, ...,
$s7) and $ra from the Stack.
Return control to the point of origin.
$ra (jr $ra).jr
instruction jumps to an address stored in a register.
Calling program must retrieve values from
$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