Recursive Factorial Function and Postfix Calculator

Tom Kelliher, CS 220

Dec. 3, 1997

Announcements

  1. Groups?

  2. Friday, Monday, and Wednesday are lab days.

  3. SPIM code for testing stack functions is available. Use it. (See home page.)

Assignment

Get started coding and testing so you can ask questions early and often.

Example Code: Factorial

  1. Draw the frame.

  2. Examine the code logic.

  3. Why is the argument stored in the frame/ $s0?

######################################################################
# 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

Postfix Calculator

See postfix.cc. With the exception of main, these routines are hand-compiled from the C++ source.

######################################################################
# postfix.hints - small example program containing some of the
#    postfix.cc routines.  Reads a line of input from the keyboard.
#    If the line's prefix is a positive integer, the value is printed.
######################################################################


               .data
nl:            .asciiz "\n"
full:          .asciiz "Trying to push onto a full stack."
empty:         .asciiz "Trying to pop from an empty stack."
prompt:        .asciiz "? "

               .align 2                # Make sure the stack is on
                                       # a word boundary.
stack:         .space 512
line:          .space 80


######################################################################
# main
######################################################################

               .text
               .globl main
main:
               # This is just an example.  You will need a larger
               # frame for main.

               sub $sp, $sp, 8
               sw $fp, 8($sp)
               sw $ra, 4($sp)
               add $fp, $sp, 8

               # Initialize globals.

               la $t8, stack
               addi $t8, $t8, 512      # $t8 is top of stack.  Points
                                       # to tos element.  Stack grows
                                       # down in memory.  Its size is
                                       # 128 words.

               la $t9, line            # $t9 is the line pointer.
                                       # Points to next character to
                                       # be examined.

               # Example code.  Reads a value from the keyboard and
               # displays it.

               li $v0, 4               # Print a prompt.
               la $a0, prompt
               syscall

               li $v0, 8               # Read a line of input
               la $a0, line
               li $a1, 80
               syscall

               jal getValue            # Call getValue.

               move $a0, $v0           # Move return value from
                                       # getValue

               li $v0, 1               # Print the value.
               syscall

               li $v0, 4               # Print a newline.
               la $a0, nl
               syscall

               la $a0, full            # Example of using die, which
                                       # takes a char pointer as a
                                       # parameter.
               jal die

               lw $ra, 4($sp)
               lw $fp, 8($sp)
               add $sp, $sp, 8
               jr $ra


######################################################################
# isdigit - decimal-digit character test.  The argument should be in
#    $a0.  The test value will be returned through $v0.  Returns 1
#    if the argument is one of ASCII 0 through 9; otherwise returns 0.
######################################################################

               .text
               .globl isdigit
isdigit:
               sub $sp, $sp, 8
               sw $fp, 8($sp)
               sw $ra, 4($sp)
               add $fp, $sp, 8

               li $v0, 0

               blt $a0, '0', isdigit_eif1
               bgt $a0, '9', isdigit_eif1

               li $v0, 1

isdigit_eif1:
               lw $ra, 4($sp)
               lw $fp, 8($sp)
               add $sp, $sp, 8
               jr $ra


######################################################################
# exit - Terminate program execution.
######################################################################

               .text
               .globl exit
exit:
               li $v0, 10
               syscall


######################################################################
# die - Print the error message pointed to by the char pointer in $a0
#    and terminate.
######################################################################

               .text
               .globl die
die:
               sub $sp, $sp, 8
               sw $fp, 8($sp)
               sw $ra, 4($sp)
               add $fp, $sp, 8

               li $v0, 4
               syscall

               li $v0, 4
               la $a0, nl
               syscall

               jal exit

               # Not reached.
               lw $ra, 4($sp)
               lw $fp, 8($sp)
               add $sp, $sp, 8
               jr $ra


######################################################################
# getValue - Read a postive integer.  The first digit is pointed to
#    by $t9, which is advanced as each digit is consumed.  The value
#    read is returned through $v0.
######################################################################

               .text
               .globl getValue
getValue:
               sub $sp, $sp, 20
               sw $fp, 20($sp)
               sw $ra, 16($sp)
               sw $s0, 12($sp)
               sw $s1,  8($sp)
               # 4($sp) is being held for local variable value.
               add $fp, $sp, 20

               li $s0, 0         # $s0 holds value.

getValue_w1:
               lb $s1, 0($t9)    # $s1 holds current character.

               move $a0, $s1     # Test the character.
               jal isdigit
               beqz $v0, getValue_ew1

               mul $s0, $s0, 10  # Update value.
               add $s0, $s0, $s1
               sub $s0, $s0, '0'

               add $t9, $t9, 1   # Increment line pointer.

               b getValue_w1

getValue_ew1:
               move $v0, $s0     # Set-up return value.

               lw $s1,  8($sp)
               lw $s0, 12($sp)
               lw $ra, 16($sp)
               lw $fp, 20($sp)
               add $sp, $sp, 20
               jr $ra



Thomas P. Kelliher
Tue Dec 2 12:05:44 EST 1997
Tom Kelliher