T4000
T4000

Reputation: 231

displaying the factorial of each value of the index of a loop does not work. MIPS

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

Answers (1)

gusbro
gusbro

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

Related Questions