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