Tom Kelliher, CS 220
Dec. 10, 2003
Friday's class will be 12:30--2:20.
Conditional execution.
Continuation of this; review for the final.
Consider the following code fragment:
int min(int, int);
int factorial(int);
void main(void)
{
int i = 3;
int j = 5;
int k;
k = min(i + 3, j);
/* Current values of i, j, k? */
k = factorial(5);
}
int min(int a, int b)
{
int i;
if (a < b)
i = a;
else
i = b;
b = 0;
return i;
}
int factorial(int n)
{
if (n <= 1)
return 1;
else
return n * factorial(n - 1);
}
Notes:
factorial() managed?

Scratch-pad storage on top of the stack.
factorial uses $s0 and has a local
copy of n (inefficient).

Example code snippets:
lw $s0, 4($fp) sw $s0, -12($fp) sw $s0, 0($sp) sub $sp, $sp, 4
$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.
Program parameters.
$ra (among others) and executes
jr $ra.
Use this sequence. Assume caller is calling callee.
Caller:
(C: last pushed first.)
jal callee
Callee:
$sp.
Number of words needed:
$fp and $ra.
$sx register used.
$fp, $ra, callee save), using
$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:
#include <stdio.h>
int getnum(void);
int factorial(int n);
int main()
{
int value;
printf("Enter 0 to exit.\n");
value = getnum();
while (value != 0)
{
printf("Factorial: %d\n", factorial(value));
value = getnum();
}
return 0;
}
int getnum(void)
{
int num;
printf("Number: ");
scanf("%d", &num);
return num;
}
int factorial(int n)
{
if (n <= 1)
return 1;
return n * factorial(n - 1);
}

# 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