MIPS - Prints the input next to output

Viewed 57

I'm learning MI trying to write a factorial program in MIPS Assembly code for which

3! = 6 (my output shows it 36)(input next to output)
4! = 24(my output shows it as 424)

Here is my code. What should I do to get rid of printing the input?

         .data
num:     .asciiz "\nPlease enter a number: "
num2:     .asciiz"\nPlease give your second number : "
respon:   .asciiz "\nThe factorial of the entered number is: "
nl:       .asciiz"\n"
        .text

fact:
        beqz $a0,return1

        li $v0, 1
        li $t0, 1

fact_loop:
        bgt $t0, $a0, end_fact_loop
        mul $v0, $v0, $t0
        addi $t0, $t0, 1

        j fact_loop

end_fact_loop:
        jr $ra

return1:
        li $v0, 1
        jr $ra

main:   
        li $v0, 4
        la $a0, num
        syscall

        li $v0, 5
        syscall
        move $t0, $v0

        li $v0, 4
        la $a0, respon
        syscall

        li $v0, 1
        move $a0, $t0
        syscall

        jal fact
        move $t0, $v0

        li $v0, 1
        move $a0, $t0
        syscall

        li $v0, 4
        la $a0, nl
        syscall
        
 ################################
        li $v0, 4
        la $a0, num2
        syscall

        li $v0, 5
        syscall
        move $t0, $v0

        li $v0, 4
        la $a0, respon
        syscall

        li $v0, 1
        move $a0, $t0
        syscall
        jal fact

        move $t0,$v0

        li $v0, 1
        move $a0, $t0
        syscall

        li $v0, 10
        syscall
2 Answers

To get rid of printing the input you have to remove the syscall you are issuing to print them.

That is, before jal-ing fact (both times) you are issuing these instructions:

    li $v0, 1
    move $a0, $t0
    syscall

Just, remove the first and third instruction and keep the move as you use it on your fact routine:

    move $a0, $t0

A few suggestions:

  • Add a comment to each functional chunk of code.
  • Use a single-step to debug so you can see what's happening where.
  • Simplify the code to a minimal failing example. If you have two chunks of code both exhibiting the same problem, remove one of them and focus on the first without distractions and noise from the second.
  • Prune unnecessary code. For example, the return1: block and beqz $a0,return1 are superfluous because the main factorial loop will exhibit the same behavior automatically -- you don't need to handle $a0 == 0 specially.

Having followed these tips, I wound up with the following program:

    .data
num:     .asciiz "\nPlease enter a number: "
num2:    .asciiz "\nPlease give your second number : "
respon:  .asciiz "\nThe factorial of the entered number is: "
nl:      .asciiz "\n"
    .text

fact:
    li $v0, 1
    li $t0, 1

fact_loop:
    bgt $t0, $a0, end_fact_loop
    mul $v0, $v0, $t0
    addi $t0, $t0, 1
    j fact_loop

end_fact_loop:
    jr $ra

main:
    # print prompt "Please enter a number: "
    li $v0, 4
    la $a0, num
    syscall

    # get user input for first fact call
    li $v0, 5
    syscall
    move $t0, $v0

    # call fact(n)
    move $a0, $t0
    jal fact
    move $t0, $v0

    # print "factorial is..."
    li $v0, 4
    la $a0, respon
    syscall

    # print the result of fact(n)
    li $v0, 1
    move $a0, $t0
    syscall

    # print newline
    li $v0, 4
    la $a0, nl
    syscall
    
    # exit program
    li $v0, 10
    syscall

The problem of double-printing is caused by this code:

    li $v0, 1
    move $a0, $t0
    syscall

The move $a0, $t0 is necessary to set up the fact call, but we don't want li $v0, 1 and syscall, which prints the argument without a newline before the result of fact, causing your unwanted output.

A good technique to prevent this in the future is ensuring your argument set-up for the function call to fact happens right before the jal.

I'll leave it as an exercise to adapt this to your second chunk of code, which has the same extra syscall to service 1 (print integer).

Related