# # 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: # int factorial(int N) { # int result = 1; # for (int i = 2; i <= N; ++i) { # result *= i; # } # return result; # } # in C with goto: # int factorial(int N) { # int result = 1; # int i = 2; # loop: # if (i > N) goto end # result *= i; # i += 1 # goto loop # end: # return result; # } 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) # # register usage: # $s0 for N (argument) # $s1 for result # $s2 for i addi $s0, $a0, 0 # int result = 1; li $s1, 1 # int i = 2; li $s2, 2 # factorial_loop: # if (i > N) goto factorial_end slt $t0, $s0, $s2 bne $t0, $zero, factorial_end # result *= i; mul $s1, $s1, $s2 # i += 1 addi $s2, $s2, 1 # goto factorial_loop j factorial_loop # end: factorial_end: # return result; addi $v0, $s1, 0 # closing linkage # "unwind the stack" # (restore registers, get return address, restore stack pointer) 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"