# # program to get an integer N from user, # compute and print N! # # loop 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: # result = 1 # for (int i = 1; i <= n; ++i) # result *= i factorial: # opening linkage (save return address and registers) # save all $s registers even if we aren't using them -- "good practice" addi $sp, $sp, -4 sw $ra, 0($sp) 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) # $a0 has n # $s0 for result # $s1 for i # result = 1 addi $s0, $zero, 1 # i = 1 addi $s1, $zero, 1 factorial_loop: # if (i > n) goto factorial_loop_end slt $t0, $a0, $s1 bne $t0, $zero, factorial_loop_end # result *= i mul $s0, $s0, $s1 # ++i addi $s1, $s1, 1 # j factorial_loop j factorial_loop factorial_loop_end: addi $v0, $s0, 0 # 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"