# # program to get an integer N from user, # compute and print N! # # recursive version # .text .globl main main: # # opening linkage (save return address) # addi $sp, $sp, -4 sw $ra, 0($sp) # # prompt # la $a0, prompt li $v0, 4 # "print string" syscall syscall # # get input N # li $v0, 5 # "read int" syscall syscall addi $s0, $v0, 0 # save result in $s0 # # $s0 for N # $s1 for result # # # echo # la $a0, echo li $v0, 4 # "print string" syscall syscall addi $a0, $s0, 0 li $v0, 1 # "print int" syscall syscall la $a0, nl li $v0, 4 # "print string" syscall syscall # # check for negative value # slt $t0, $s0, $zero beq $t0, $zero, input_okay la $a0, error li $v0, 4 # "print string" syscall syscall j end input_okay: # # compute N! (into $s1) and print # add $a0, $s0, $zero # $a0 <- N jal factorial add $s1, $v0, $zero # # print result # la $a0, result li $v0, 4 # "print string" syscall syscall addi $a0, $s1, 0 # get result li $v0, 1 # "print int" syscall syscall la $a0, nl li $v0, 4 # "print string" syscall syscall # # closing linkage (get return address and restore stack pointer) # end: lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra # # factorial procedure: # # in C: # int factorial(int N) { # if (N <= 0) # return 1; # else # return N * factorial(N-1); factorial: # opening linkage (save return address and registers) # we save all registers even though we aren't using them -- "good practice" addi $sp, $sp, -4 sw $ra, 0($sp) # here we could continue pushing things onto the stack by repeatedly # decrementing the stack pointer, but it's quicker to do one decrement .... addi $sp, $sp, -32 sw $s0, 0($sp) sw $s1, 4($sp) sw $s2, 8($sp) sw $s3, 12($sp) sw $s4, 16($sp) sw $s5, 20($sp) sw $s6, 24($sp) sw $s7, 28($sp) # # if (N > 0) goto recurse: # slt $t0, $zero, $a0 # $t0 <- is 0 < N? bne $t0, $zero, recurse # return 1 addi $v0, $zero, 1 # return value of 1 j factorial_end recurse: # int temp = factorial(N-1); # return temp * N; add $s0, $a0, $zero # $s0 <- N addi $a0, $a0, -1 # $a0 <- N-1 jal factorial # after this, $v0 has result # of recursive call mul $v0, $s0, $v0 # $v0 <- N * temp # closing linkage # "unwind the stack" # (restore registers, get return address, restore stack pointer) factorial_end: lw $s7, 28($sp) lw $s6, 24($sp) lw $s5, 20($sp) lw $s4, 16($sp) lw $s3, 12($sp) lw $s2, 8($sp) lw $s1, 4($sp) lw $s0, 0($sp) addi $sp, $sp, 32 lw $ra, 0($sp) addi $sp, $sp, 4 # return to caller jr $ra .end main # # area for variables and constants # .data prompt: .asciiz "Enter a non-negative integer:\n" error: .asciiz "Error -- negative input\n" echo: .asciiz "You entered:\n" result: .asciiz "Result:\n" nl: .asciiz "\n"