Reputation: 231
I am trying to display the factorial of the current value of the index of a loop in MIPS but, my loop does not work at all. It keeps freezing every time I run the code. Let say I have a for loop such that (i=1; i<=5; i++), for each value of i, I would like to display the current factorial(i). The number 5, is actually provided by the user, in other words, the number can change(1-10). I have tried to figure out why my loop causes the code to freeze, but I have no clues so far. Your help will be very appreciated. The code is bellow.
.data # data declaration section; specifies values to be stored
# in memory and labels whereby the values are accessed
Prompt: .asciiz "\nEnter the number to compute the factorial:\n"
message: .asciiz "\nResult of computation is:\n"
result: .word 0
#--------------------------------
# main function |
#--------------------------------
.text # Start of code section
.globl main
main: # Execution begins at label "main". The prompt is displayed.
li $v0, 4 # system call code for printing string = 4
la $a0, Prompt # load address of string to be printed into $a0
syscall # call operating system to perform operation;
# $v0 specifies the system function called;
# syscall takes $v0 (and opt arguments)
# Read integer N
li $v0, 5
syscall
move $t0, $v0 #copy integer N into $t0
li $t1, 1 #initialize i=1
loop:
blt $t0, $t1, exit_loop # if number<1, exit...
move $a0, $t0 # copy N into $ao
jal fact #else call fact
sw $v0, result
li $v0, 4 #Display message
la $a0, message
syscall
li $v0, 1 #print result
lw $a0, result
syscall
sub $t0, $t0, 1 #Decrement N by one, N--
j loop
exit_loop:
jr $ra #return address
exit: #exit the program
li $v0, 10
syscall
.globl fact
.ent fact
fact:
subu $sp, $sp, 8
sw $ra, ($sp)
sw $s0, 4($sp)
li $v0, 1 #check base case
beq $a0, 0, end_fact
move $s0, $a0 #fact(n-1)
sub $a0, $a0, 1
jal fact
mul $v0, $s0, $v0 #n*fact(n-1)
end_fact:
lw $ra ($sp)
lw $s0, 4($sp)
addu $sp,$sp, 8
jr $ra
#end of factorial function
Upvotes: 0
Views: 635
Reputation: 22585
Your problem is in the instruction at exit_loop
label:
exit_loop:
jr $ra #return address
You are jumping again into the loop because you haven't saved $ra
at the start of your main function and you are also not restoring it before issuing that jr
In fact, your code, as is, should just terminate (syscall
10) and not issue a jump because you are implementing the main function and not a function to be called from elsewhere.
So, i'd change that code to:
exit_loop:
li $v0, 10
syscall
Looking a bit more into your code, you already have that code (on label exit
), so you might just remove your exit_loop code and branch to exit
instead of exit_loop
in the branch that goes just after loop
label.
Upvotes: 1