MOA #21 24-3-1998
The MIPS CPU contains 32 general purpose 32-bit registers: $0 - $31. Register $0 contains the hardwired value 0.
The recommended (i.e., not enforced by hardware) usage of these registers is as given in Table 2 of the document SPIM S20: A MIPS R2000 Simulator by J. Larus.
Apart from its generic $n name, a register has also a more descriptive name according to its intended usage. The following ones are useful in procedure calls.
Like what we have described before using a hypothetical procedure call model, a stack frame is created when a procedure (caller) calls another one (callee).
The stack frame contains data that is partly the caller's (return address, saved registers) and partly the callee's (passed arguments, local variables). But in general we call this stack frame the callee's stack frame.
The following figure shows the layout of a stack frame. The frame pointer ($fp) points at the first word in the frame, and the stack pointer ($sp) points at the first free word above the frame.
The first four arguments are passed in registers ($a0-$a3), and hence the first word of the stack frame stores the fifth argument if there is one.
To load the fifth argument into a register, the callee procedure can issue an instruction such as
lw $t0, 0($fp)[This seems to violate the typical use of a stack (i.e., accessing only the top element). Well, the stack is used here mainly to maintain the LIFO behavior of procedure calls.]
Let's see what the caller has to do, and then the callee, in a procedure call.
The caller:
The callee:
Here is an example of procedure call: a program to calculate the factorial of the integer 10. The C++ version looks like the following.
#include <iostream.h> int fact(int n) { if (n <= 1) return 1; else return n * fact(n-1); } void main() { cout << "The factorial of 10 is " << fact(10) << endl; }Here is the assembly language program (runnable in SPIM):
.globl main .data Msg: .ascii "the factorial of 10 is " .text #################### Main program #################### main: li $a0, 10 # Put argument (10) in $a0 jal Fact # The call - Fact(10) move $t0, $v0 # Save result in $a1 li $v0, 4 # Print Msg la $a0, Msg syscall li $v0, 1 # Print result move $a0, $t0 syscall li $v0, 10 # exit syscall #################### Function Fact(n) #################### Fact: subu $sp, $sp, 32 # Create 32-byte stack frame sw $ra, 20($sp) # Save return address sw $fp, 16($sp) # Save frame pointer addu $fp, $sp, 32 # Set up frame pointer sw $a0, 0($fp) # Save argument (n) bgtz $a0, More # Branch if n > 0 li $v0, 1 # else return 1 j Ret # Jump to return code More: subu $a0, $a0, 1 # Compute n-1 jal Fact # Fact(n-1) lw $v1, 0($fp) # Retrieve saved n mul $v0, $v0, $v1 # Fact(n-1) * n Ret: lw $ra, 20($sp) # Restore $ra lw $fp, 16($sp) # Restore $fp addu $sp, $sp, 32 # Pop stack j $ra # Return to callerSome notes are in order: