通过编写delay和time2string子程序完成时钟程序。time2string的说明:寄存器$a0包含内存中某个区域的地址,对于time2string的输出来说,该地址的大小是合适的。寄存器$a1的16个最低有效位包含时间信息,其被组织为四个每个4位的NBCD编码数字。寄存器$a1中的所有其他位可以具有任何值,必须忽略。
这就是我到目前为止所做的,代码的其他部分没有问题,因为它们是给定的。我只写了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
1条答案
按热度按时间1aaf6o9v1#
jal ...
或返回jr $ra
之后都始终使用nop
,因此您也应该这样做,因为延迟分支似乎可能会针对您的模拟器情况设置为启用/打开。因此,在执行跳转或分支的任何地方插入nop
s-请注意,这包括beq
和bne
。(如果正在使用延迟分支,并且您忘记在某个地方使用nop
,那么可能会非常混乱,无法确定发生了什么或出了什么问题。addi
提取您想要使用andi
的数字,所以只是操作码中的一个错字(但您应该能够观察到这些并没有按照您的意图工作,并建议您不是单步调试)。您只需要一个条件分支来测试一个条件,而不需要使用另一个分支来测试完全相反的条件。你能想出一个能在那里工作的分支吗?不要忘记在分支后使用
nop
。此外,应该尽可能测试0而不是1,并且,0作为$0-
beq $t0, 1, low
会更好地作为bne $t0, $0, low
(与我们在这里知道的值相同,t0必须是0或1),就像你的beq $t0, 0, high
作为beq $t0, $0, high
一样。有了这些变化,你应该更接近正确的时钟。然而,还有其他的bug,你应该学会单步调试来观察每一行代码的执行,看看它的结果是否如预期的那样。调试汇编与调试其他代码基本相同:单步运行每一行,观察这一行对程序状态的影响,并与您认为这一行应该做的或应该做的进行比较。