Stimulate a clock using nested loops in mips

951 views Asked by At

Im trying to make a program that output time like this: 00:00:00 all the way to 12:59:59

here is my code it only loops around the second and nothing else is outputs it output from 0:0:0 to 0:0:59

what am I doing wrong and how can i get the output in format ##:##:##

.data
             str2:  .asciiz ":"
             space: .asciiz "\n"
.text

 main:

    li $t0,1

hour:
    bgt $t0,12,exit

    minutes:
         bgt $t1,59,hour 
         seconds:
            bgt $t2,59,minutes 

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

        li $v0,4
            la $a0,str2 #load and print string
            syscall

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

        li $v0,4
            la $a0,str2 #load and print string
            syscall

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

        addi $v0, $zero, 4  
            la $a0, space       
        syscall

            addi $t2,$t2,1
        j seconds
         addi $t1,$t1,1
     j minutes   


    addi $t0,$t0,1

    j hour  

exit:
2

There are 2 answers

0
paxdiablo On BEST ANSWER
minutes:
    bgt $t1,59,hour     ; 1
seconds:
    bgt $t2,59,minutes  ; 2
    li  $v0, 1          ; 3
    :
    addi $t2,$t2,1
    j seconds

When $t2 eventually gets to 60, that code segment you have there is going to be an infinite loop.

Nowhere in the code are you actually setting $t2(secs) back to zero and incrementing $t1(mins) so, once $t2 hits 60 and you jump to seconds, here's the execution path: 2, 1, 2, 1, 2, ..., with no chance of advancing to 3 again.

As to how to fix it, don't just jump back to minutes when $t2 overflows, you have to set $t2 back to zero and increment $t1. Then you need to check $t1 for overflow and so on.

Since it's probably classwork, I'll offer pseudo-code (of an assembler variety) only, but possibly the best way to structure your code would be:

start:
    $t0 = 0
    $t1 = 0
    $t2 = -1

loop:
    $t2 = $t2 + 1
    if $t2 < 60 goto skipmin
    $t2 = 0                   ; special when secs -> 60
    $t1 = $t1 + 1

skipmin:
    if $t1 < 60 goto skiphour
    $t1 = 0                   ; special when mins -> 60
    $t0 = $t0 + 1
    if $t0 == 24 goto end     ; stop at 24:00:00

skiphour:
    display $t0:$t1:$t2
    goto loop

end:
    stop program

As to how to display values with leading zeroes, again with pseudo-code (for just the seconds value, you'll have to expand it to handle minutes and hours):

    if $t2 > 9 goto nozerosec
    syscall 4 with $a0 pointing at "0"
nozerosec:
    syscall 1 with $a0 loaded from $t2

This simply works by checking the value you're going to output and, if it's less than 10, outputting a leading zero first.

This is assuming (as it seems to be) that syscall 1 is for outputting a value in $a0 and syscall 4 is for outputting a string pointed to by $a0.

And, for extra credits, you can make the padded output a separate function to be called rather than repeating yourself in the main program.

0
A P S On

You might want to add another loop for the minutes hours and seconds, such as the following:

bgt $t0, 12, exit

bgt $t1, 59, movemin

bgt $t2, 59, movesec

movesec: 

     addi $t1, $t1, 1
     move $t2, $t2, 0

movemin:
     addi $t2, $t2, 1
     move $t1, $t1, 0

exit:
     ori $v0, 0, 10
     syscall