Search code examples
mipsmips32mars-simulator

Stimulate a clock using nested loops in mips


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:

Solution

  • 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.