我有一个关于如何编写一个名为tim2string
的函数的具体描述,我已经编写了这个函数,但我不确定我是否按照它在描述中的说法进行操作。我试图在MARS上运行我的代码,我得到了这个ERROR
。注意在代码的末尾添加了tim2string
。
timetemplate.asm line 99: Runtime exception at 0x00400118: address out of range 0x00005958
功能说明如下
名称:子程序必须被称为time2string。 参数(二):寄存器$ a0包含内存中某个区域的地址,适合大小 time2string的输出。寄存器$ a1的16个最低有效位包含有组织的时间信息 作为四个NBCD编码的数字,每个4位。寄存器$ a1中的所有其他位可以具有任何值 被忽略了。
示例:寄存器$ a0可以包含地址0x100100017,寄存器$ a1可以包含值0x00001653。 返回值:无。 必要的行动:
必须将以下六个字符序列写入内存区域 寄存器$ a0指出。
1)两个ASCII编码的数字显示分钟数,根据另外两个 输入参数的重要NBCD编码数字。示例:'1','6'(ASCII 0x31,0x36):
2)冒号字符(ASCII:,代码0x3A)。
3)两个ASCII编码的数字显示秒数,根据两个少 输入参数的重要NBCD编码数字。示例:'5','3'(ASCII 0x35,0x33)。 4.空字节(ASCII NUL,代码0x00)。 注意:必须使用函数hexasc将每个NBCD编码的数字转换为相应的数字 ASCII码。使用sb指令将每个字节存储在目标位置。宏PUSH和POP 用于保存和恢复寄存器。
# timetemplate.asm
# Written 2015 by F Lundevall
# Copyright abandonded - this file is in the public domain.
.macro PUSH (%reg)
addi $sp,$sp,-4
sw %reg,0($sp)
.end_macro
.macro POP (%reg)
lw %reg,0($sp)
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) #load the adress contained in $t0 into $a1
jal time2string
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
addiu $t0,$t0,1 # increase
andi $t1,$t0,0xf # check lowest digit
sltiu $t2,$t1,0xa # if digit < a, okay
bnez $t2,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
jr $ra # return
nop
# you can write your code for subroutine "hexasc" and below this line
#
hexasc:
andi $a0,$a0,0xf #only 4 least significant bits ignore other bits
addi $v0,$zero,0x30 #$v0 = 0x30 ('0')
addi $t0,$zero,0x9 #t0 = 0x9
ble $a0,$t0,L1 #branch if a0 <= 0x9
nop
addi $v0,$v0,0x7 #v0 = v0 +0x7
L1:
add $v0,$a0,$v0 #v0 = V0 +a0
jr $ra
nop
delay:
jr $ra
nop
time2string:
PUSH ($t2)
PUSH ($t0)
PUSH ($a1)
lb $t0, 0($a1) #load one byte from a1 "LINE 99" ERROR
andi $t2, $t0,0xf #check the 4 lowest bits ignore other
jal hexasc # call hexasc
nop
sb $t0, 0($a1) #stor back that byte in a1
lb $t0, 1($a1) # load the next byte
andi $t2, $t0,0xf0
jal hexasc
nop
sb $t0, 1($a1)
lb $t0, 2($a1)
andi $t2, $t0,0xf00
jal hexasc
nop
sb $t0, 2($a1)
lb $t0, 3($a1)
andi $t2, $t0,0xf000
jal hexasc
nop
sb $t0, 3($a1)
POP ($a1)
POP ($t0)
POP ($t2)
jr $ra
nop
更新1.0
到目前为止我写了time2string
函数已经取得了一些进展
而且我还需要一些帮助。
我单步执行我的代码,它正常工作,直到这一行sb $v0, 0($t0) #stor that 4 bits in that location that a0 points to
我收到此错误timetemplate.asm line 115: Runtime exception at 0x00400158: address out of range 0x00000009
这是更新后的代码
time2string:
PUSH ($t0)
PUSH ($t1)
PUSH ($t2)
PUSH ($t3)
PUSH ($t4)
PUSH ($t5)
PUSH ($ra) #nested subroutine must store $ra too
add $t0,$0,$a0 #contaisn the adress of string (timstr)
add $t1,$0,$a1 #contains the time-info(0x5957)
andi $t2,$t1,0xf000 #check the 4 most signifaicant bits ignore other bits
srl $a0,$t2,12 #shift the MSB to LSB position (hexasc take only 4 bits in the LSB position)
jal hexasc # call hexasc
nop
sb $v0, 0($t0) #stor that 4 bits in that location that a0 points to
andi $t3,$t1,0x0f00 #mask to get those 4 bits you and ignore other bits
srl $a0,$t3,8 #shift those bits to the LSB position(0x000f)
jal hexasc
nop
sb $v0,1($t0)
li t5,0x3A
sb $t5,2($t0)
andi $t4,$t1,0x00f0
srl $a0,$t4,4
jal hexasc
nop
sb $v0,3($t0)
move $a0,$t1
jal hexasc
nop
sb $v0, 4($t0)
POP ($ra)
POP ($t5)
POP ($t4)
POP ($t3)
POP ($t2)
POP ($t1)
POP ($t0)
jr $ra
nop
答案 0 :(得分:1)
lb $t0, 0($a1) #load one byte from a1
这将从地址a1
的内存中加载一个字节。
但a1
不包含有效地址,它包含BCD时间值,如0x5958
,即时间59:58。
因此您不需要从内存加载时间值,您已经加载了a1
中的值。你必须分别挑选每组4位(从低16位),这是4位数字的编码。
哦,这个:
我试图在MARS上运行我的代码
那不是,人们如何在大会上编程。你没有运行你的代码。您逐步调试调试器中的单个指令,在每条指令之后进行验证,它确实只更改了应该更改的寄存器/内存,并且只改变了应该如何更改它的方式。
(这就是为什么你需要第一个描述算法的英文评论,因为否则你无法推断指令是否做了你想做的......当然它总会做,做什么,根据CPU文档,当你的指令本身无法正常执行时,你几乎不会遇到这种情况(虽然技术上可行,当一些电子“跳过”所谓的路径的“墙壁”时,通常在被一些质子击中之后从X射线/等...也许如果你能活得足够长,它可能会发生在你身边一两次......很可能你永远不会注意到,因为SW可能会幸存下来,或像往常一样崩溃来自代码错误))
还要确保你避免大脑在你身上耍花招,采取快捷方式来节省它的努力,所以不用你的大脑读取屏幕上的内容,它会试着告诉你,你想要写什么并看到那里
就像在代码sb $t0,0($a1)
而不是sb $t0,0($a0)
中写一样,如果您在编写代码后不久会尝试重新阅读来源,那么您将阅读sb $t0,0($a0)
,除非您专注非常努力,确保你的大脑不会欺骗你。
同样适用于调试和检查寄存器中的结果值等。如果您在1
中期望值为t1
,并且偶然在t2
中结束,则可能很容易错过了1
确实在t2
而不是在t1
中发生变化这一事实,因为您的大脑主要关心结果是1
。等。
这很棘手。这就是为什么人们喜欢汇编,并编写几乎所有内容的原因。