汇编实现简易时钟:补全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
关键修正说明
delay子程序:
- 实现双层循环结构,外层循环对应传入的秒数参数,内层循环通过固定计数实现约1秒延迟(可根据运行环境调整内层循环计数值
0xFFFFF)。 - 解决原代码无延迟逻辑导致时钟飞速跳转的问题。
- 实现双层循环结构,外层循环对应传入的秒数参数,内层循环通过固定计数实现约1秒延迟(可根据运行环境调整内层循环计数值
time2string子程序:
- 修复分钟低位提取错误:原代码错误复用小时高位提取逻辑,改为直接取
$s1的低4位。 - 对所有提取的NBCD数字增加
andi $a1, $a1, 0xF操作,确保只保留低4位,符合需求中“忽略其余位”的要求。 - 优化代码注释,使逻辑更清晰。
- 修复分钟低位提取错误:原代码错误复用小时高位提取逻辑,改为直接取
内容的提问来源于stack exchange,提问作者User
相关产品推荐
相关产品推荐

