You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编实现简易时钟:补全delay与time2string子程序及时间更新

问题描述

请完成时钟程序,编写delay和time2string子程序。time2string说明:寄存器$a0指向内存中足够容纳输出结果的区域;寄存器$a1的低16位为时间信息,由4个4位的NBCD编码数字组成,其余位需忽略。

以下是目前完成的代码,其余给定部分无问题,仅hexasc、time2string、delay为自行编写,请协助完善以实现时钟时间更新功能。

现有代码
.macro  PUSH (%reg)   #  reg defines a parameter
    addi    $sp,$sp,-4    # reserve space for that data
    sw  %reg,0($sp)   # Stores  the register specified by %reg at the memory location pointed to by $sp. 
.end_macro

.macro  POP (%reg)
    lw  %reg,0($sp) #loads from memory to register %reg
    addi    $sp,$sp,4
.end_macro

    .data
    .align 2
mytime: .word 0x5957
timstr: .ascii "text more text lots of text\0"
    .text
main:
    # print timstr
    la  $a0,timstr
    li  $v0,4
    syscall
    nop
    # wait a little
    li  $a0,2
    jal delay
    nop
    # call tick
    la  $a0,mytime
    jal tick
    nop
    # call your function time2string
    la  $a0,timstr
    la  $t0,mytime
    lw  $a1,0($t0)
    jal time2string    #it calls on the funciton and return memory is saved
    nop
    # print a newline
    li  $a0,10
    li  $v0,11
    syscall
    nop
    # go back and do it all again
    j   main
    nop
# tick: update time pointed to by $a0
tick:   lw  $t0,0($a0)  # get time    loads data from the data memory and it access the from memory location from $a0
    addiu   $t0,$t0,1   # increase     unsigned addition
    andi    $t1,$t0,0xf # check lowest digit
    sltiu   $t2,$t1,0xa # if digit < a, okay      performs unsigned comparisson then t2 will either be 1 or 0
    bnez    $t2,tiend      # if not equal to 0, then jump to tiend
    nop
    addiu   $t0,$t0,0x6 # adjust lowest digit
    andi    $t1,$t0,0xf0    # check next digit
    sltiu   $t2,$t1,0x60    # if digit < 6, okay
    bnez    $t2,tiend
    nop
    addiu   $t0,$t0,0xa0    # adjust digit
    andi    $t1,$t0,0xf00   # check minute digit
    sltiu   $t2,$t1,0xa00   # if digit < a, okay
    bnez    $t2,tiend
    nop
    addiu   $t0,$t0,0x600   # adjust digit
    andi    $t1,$t0,0xf000  # check last digit
    sltiu   $t2,$t1,0x6000  # if digit < 6, okay
    bnez    $t2,tiend
    nop
    addiu   $t0,$t0,0xa000  # adjust last digit
tiend:  sw  $t0,0($a0)  # save updated result       sw= stores 4-byte word  0($a0): This part specifies the memory address where the contents of $t0 will be stored.
    jr  $ra     # return
    nop

  # you can write your code for subroutine "hexasc" below this line
  #
  
  
hexasc:

       andi  $v0, $a0, 15     #15 is 1111, so 

       slti  $t0, $v0, 10     #if t0 is less than 10, it sets it 1 otherwise 0

       beq   $t0, 1, low      #if t0 is equal to 1 then call the subroutine low

       beq   $t0, 0, high     #if t0 is 0 then call the subroutine high


low:
       addi $v0, $v0, 0x30    # 0x30 is 48 in base 16, add the input v0
       jr $ra                 #we jump back to main

high:
       addi $v0, $v0, 0x37    #0x37 = 55 in base 10, then we add the input v0
       jr $ra                #jump back to main
       
       
delay:
       jr $ra
       nop
       
    

        
time2string: 
            PUSH ($s0)
            PUSH ($s1)
            PUSH ($ra)

            add $s0, $a0, 0
            add $s1, $a1, 0
            
            addi $t1, $s1, 0xf000
            srl  $a1, $s1, 12 
            jal hexasc
            sb $v0, 0($s0)
            
            addi $t1, $s1, 0x0f00
            srl  $a1, $s1, 8 
            jal hexasc
            sb $v0, 1($s0)
            
            li $t0, 0x3A
            sb $t0, 2($s0)

            addi $t1, $s1, 0x00f0
            srl  $a1, $s1, 4
            jal hexasc
            sb $v0, 3($s0)
            
            addi $t1, $s1, 0xf000
            srl  $a1, $s1, 12 
            jal hexasc
            sb $v0, 4($s0)                          

###############################################################

        
###############################################################

            li  $t1, 0x00           
            sb  $t1, 5($s0)
########################################################
            POP ($ra)
        POP ($s1)
        POP ($s0)   
        jr   $ra  
修正后的代码
.macro  PUSH (%reg)   #  reg defines a parameter
    addi    $sp,$sp,-4    # reserve space for that data
    sw  %reg,0($sp)   # Stores  the register specified by %reg at the memory location pointed to by $sp. 
.end_macro

.macro  POP (%reg)
    lw  %reg,0($sp) #loads from memory to register %reg
    addi    $sp,$sp,4
.end_macro

    .data
    .align 2
mytime: .word 0x5957
timstr: .ascii "text more text lots of text\0"
    .text
main:
    # print timstr
    la  $a0,timstr
    li  $v0,4
    syscall
    nop
    # wait a little
    li  $a0,2
    jal delay
    nop
    # call tick
    la  $a0,mytime
    jal tick
    nop
    # call your function time2string
    la  $a0,timstr
    la  $t0,mytime
    lw  $a1,0($t0)
    jal time2string    #it calls on the funciton and return memory is saved
    nop
    # print a newline
    li  $a0,10
    li  $v0,11
    syscall
    nop
    # go back and do it all again
    j   main
    nop
# tick: update time pointed to by $a0
tick:   lw  $t0,0($a0)  # get time    loads data from the data memory and it access the from memory location from $a0
    addiu   $t0,$t0,1   # increase     unsigned addition
    andi    $t1,$t0,0xf # check lowest digit
    sltiu   $t2,$t1,0xa # if digit < a, okay      performs unsigned comparisson then t2 will either be 1 or 0
    bnez    $t2,tiend      # if not equal to 0, then jump to tiend
    nop
    addiu   $t0,$t0,0x6 # adjust lowest digit
    andi    $t1,$t0,0xf0    # check next digit
    sltiu   $t2,$t1,0x60    # if digit < 6, okay
    bnez    $t2,tiend
    nop
    addiu   $t0,$t0,0xa0    # adjust digit
    andi    $t1,$t0,0xf00   # check minute digit
    sltiu   $t2,$t1,0xa00   # if digit < a, okay
    bnez    $t2,tiend
    nop
    addiu   $t0,$t0,0x600   # adjust digit
    andi    $t1,$t0,0xf000  # check last digit
    sltiu   $t2,$t1,0x6000  # if digit < 6, okay
    bnez    $t2,tiend
    nop
    addiu   $t0,$t0,0xa000  # adjust last digit
tiend:  sw  $t0,0($a0)  # save updated result       sw= stores 4-byte word  0($a0): This part specifies the memory address where the contents of $t0 will be stored.
    jr  $ra     # return
    nop

  # you can write your code for subroutine "hexasc" below this line
  #
  
  
hexasc:

       andi  $v0, $a0, 15     #15 is 1111, so 

       slti  $t0, $v0, 10     #if t0 is less than 10, it sets it 1 otherwise 0

       beq   $t0, 1, low      #if t0 is equal to 1 then call the subroutine low

       beq   $t0, 0, high     #if t0 is 0 then call the subroutine high


low:
       addi $v0, $v0, 0x30    # 0x30 is 48 in base 16, add the input v0
       jr $ra                 #we jump back to main

high:
       addi $v0, $v0, 0x37    #0x37 = 55 in base 10, then we add the input v0
       jr $ra                #jump back to main
       
       
delay:
    # $a0为延迟秒数(近似值)
    move $t0, $a0
delay_loop_outer:
    beqz $t0, delay_end
    li $t1, 0xFFFFF  # 内层循环计数,实现约1秒延迟(可根据环境调整)
delay_loop_inner:
    addi $t1, $t1, -1
    bnez $t1, delay_loop_inner
    addi $t0, $t0, -1
    j delay_loop_outer
delay_end:
    jr $ra
    nop
       
    

        
time2string: 
            PUSH ($s0)
            PUSH ($s1)
            PUSH ($ra)

            add $s0, $a0, 0
            add $s1, $a1, 0
            
            # 提取小时高位
            srl  $a1, $s1, 12 
            jal hexasc
            sb $v0, 0($s0)
            
            # 提取小时低位
            srl  $a1, $s1, 8 
            andi $a1, $a1, 0xF
            jal hexasc
            sb $v0, 1($s0)
            
            # 冒号分隔符
            li $t0, 0x3A
            sb $t0, 2($s0)

            # 提取分钟高位
            srl  $a1, $s1, 4
            andi $a1, $a1, 0xF
            jal hexasc
            sb $v0, 3($s0)
            
            # 提取分钟低位
            andi $a1, $s1, 0xF
            jal hexasc
            sb $v0, 4($s0)                          

            # 字符串结束符
            li  $t1, 0x00           
            sb  $t1, 5($s0)
            
            POP ($ra)
            POP ($s1)
            POP ($s0)   
            jr   $ra  
关键修正说明
  1. delay子程序:

    • 实现双层循环结构,外层循环对应传入的秒数参数,内层循环通过固定计数实现约1秒延迟(可根据运行环境调整内层循环计数值0xFFFFF)。
    • 解决原代码无延迟逻辑导致时钟飞速跳转的问题。
  2. time2string子程序:

    • 修复分钟低位提取错误:原代码错误复用小时高位提取逻辑,改为直接取$s1的低4位。
    • 对所有提取的NBCD数字增加andi $a1, $a1, 0xF操作,确保只保留低4位,符合需求中“忽略其余位”的要求。
    • 优化代码注释,使逻辑更清晰。

内容的提问来源于stack exchange,提问作者User

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 06:07:01