Tom Kelliher, CS 220
None.
Study factorial.spim.
Definitions:
Example. Suppose main calls factorial, using an on-stack
parameter ( n) pass.
factorial uses $s0 and has a local
variable, temp:

Example code snippets:
lw $s0, 4($fp) sw $s0, -12($fp) sw $s0, 0($sp) sub $sp, $sp, 4
$sp vs. $fp.
Convention:
$v[0-1] --- function results.
$a[0-3] --- function arguments.
$t[0-9] --- caller save registers. (Except for two global
pointers, ignore these registers.)
$s[0-7] --- callee save registers.
$sp --- top of stack pointer, pointing to first free location
on execution stack.
$fp --- frame pointer, pointing to base of current frame.
$ra --- return address.
$ra (among others) and executes
jr $ra.
Use this sequence. Assume caller is calling callee.
Caller:
jal callee
Callee:
$sp.
Number of words needed:
$fp and $ra.
$sx register used.
$sp as base register.
$fp by adding frame size to $sp and storing.
$fp as
base register.
$ax registers.
$sp as base register.
$sp.
jr $ra
Caller:
Consider the following C++ code which recursively computes the factorial:
#include <iostream.h>
int getnum(void);
int factorial(int n);
int main()
{
int value;
cout << "Enter 0 to exit.\n";
value = getnum();
while (value != 0)
{
cout << "Factorial: " << factorial(value) << endl;
value = getnum();
}
return 0;
}
int getnum(void)
{
int num;
cout << "Number: ";
cin >> num;
return num;
}
int factorial(int n)
{
if (n <= 1)
return 1;
return n * factorial(n - 1);
}
Here is the corresponding SPIM program:
# factorial.spim --- A recursive SPIM program. Demonstrates function
# call and return.
.data
prompt: .asciiz "Number: "
nl: .asciiz "\n"
instr: .asciiz "Enter 0 to exit.\n"
response: .asciiz "Factorial: "
######################################################################
# main
######################################################################
.text
.globl main
main:
sub $sp, $sp, 16 # Push frame & save registers.
sw $fp, 16($sp)
sw $ra, 12($sp)
sw $s0, 8($sp)
add $fp, $sp, 16
li $v0, 4 # Print instruction.
la $a0, instr
syscall
jal getnum # Get a number from keyboard.
sw $v0, -12($fp) # Store locally.
move $s0, $v0
while1:
beqz $s0, endwhile1 # Compute until 0 entered.
li $v0, 4 # Print response prompt.
la $a0, response
syscall
move $a0, $s0 # Pass argument
jal factorial # Call
move $a0, $v0 # Copy return value to print it
li $v0, 1
syscall
li $v0, 4 # Prepare to read next number.
la $a0, nl
syscall
jal getnum
sw $v0, -12($fp) # Store number just read.
move $s0, $v0
b while1
endwhile1:
lw $s0, 8($sp) # Restore registers and pop frame.
lw $ra, 12($sp)
lw $fp, 16($sp)
add $sp, $sp, 16
li $v0, 0
jr $ra # Exit.
######################################################################
# getnum --- returns integer read from keyboard through $v0.
######################################################################
.text
getnum:
sub $sp, $sp, 12 # push frame & save registers.
sw $fp, 12($sp)
sw $ra, 8($sp)
add $fp, $sp, 12
li $v0, 4
la $a0, prompt
syscall
li $v0, 5
syscall # Value read left in $v0.
sw $v0, -8($fp)
lw $ra, 8($sp) # restore registers & pop frame.
lw $fp, 12($sp)
add $sp, $sp, 12
jr $ra
######################################################################
# factorial --- compute factorial of $a0 and return result through
# $v0
######################################################################
.text
factorial:
sub $sp, $sp, 16
sw $fp, 16($sp)
sw $ra, 12($sp)
sw $s0, 8($sp)
add $fp, $sp, 16
sw $a0, -12($fp) # Our value n.
move $s0, $a0
bgt $s0, 1, recurse # Base case. Return 1
li $v0, 1
lw $s0, 8($sp)
lw $ra, 12($sp)
lw $fp, 16($sp)
add $sp, $sp, 16
jr $ra
recurse: sub $a0, $a0, 1 # Recursive call. Compute (n-1)!
jal factorial
mul $v0, $v0, $s0 # n * (n-1)!
lw $s0, 8($sp)
lw $ra, 12($sp)
lw $fp, 16($sp)
add $sp, $sp, 16
jr $ra