Assembly 在MIPS中编写子例程,将整数0到15转换为ASCII字符';0';通过';F';
编写一个小的子程序,将0到15范围内的数字转换为 可打印ASCII编码字符:“0”到“9”或“A”到“F”,具体取决于数字。 对于不在0到15范围内的数字,某些位将被忽略 名称:子例程必须称为hexasc。 参数:1,在寄存器$a0中。4个最低有效位指定一个数字,从0到15。 寄存器$a0中的所有其他位可以有任何值,必须忽略。 返回值:寄存器$v0中的7个最低有效位必须是ASCII码,如下所述。 函数返回时,所有其他位必须为零。 所需操作:该函数必须将输入值0到9转换为数字的ASCII码 分别为“0”到“9”。输入值10到15必须转换为ASCII码,以便 字母“A”至“F”分别为Assembly 在MIPS中编写子例程,将整数0到15转换为ASCII字符';0';通过';F';,assembly,mips,Assembly,Mips,编写一个小的子程序,将0到15范围内的数字转换为 可打印ASCII编码字符:“0”到“9”或“A”到“F”,具体取决于数字。 对于不在0到15范围内的数字,某些位将被忽略 名称:子例程必须称为hexasc。 参数:1,在寄存器$a0中。4个最低有效位指定一个数字,从0到15。 寄存器$a0中的所有其他位可以有任何值,必须忽略。 返回值:寄存器$v0中的7个最低有效位必须是ASCII码,如下所述。 函数返回时,所有其他位必须为零。 所需操作:该函数必须将输入值0到9转换为数字的ASCII码 分别为
.text
main:
li $a0,0 # change this to test different values
jal hexasc # call hexasc
nop # delay slot filler (just in case)
move $a0,$v0 # copy return value to argument register
li $v0,11 # syscall with v0 = 11 will print out
syscall # one byte from a0 to the Run I/O window
stop: j stop # stop after one run
nop # delay slot filler (just in case)
我在这里编写了我的hexasc
子例程,由于某种原因我不明白,所以它不起作用。我不知道我在哪一部分有bug,也许我没有按照上面的规范所说的去做。
任何帮助都将不胜感激,提前谢谢
hexasc:
addi $sp,$sp,-4 #make space on the stack
sw $a0,0($sp) #store $a0 on the stack
li $t0,0x30 #$t0 = 0x30 ('0' in ascii)
andi $a0,$a0,0xf #only 4 least significant bits is
#needed ignore other bits
loop:
add $a0,$a0,$t0 #$a0 i will think why i did this
addi $t0,$t0,1 #increment $t0 by 1
beq $t0,0x39,loop2 # if $t0 = 0x39 (9 in ascii)
j loop
li $t1,0x41 # $t1 = 0x41 ( A in ascii)
loop2:
andi $a0,$a0,0xf # only 4 LSB ignore other bits
add $a0,$a0,$t1 # ???? i will think about this
beq $t1,0x46,done # if $t1 = 0x46 (F in ascii)
j loop2
done:
add $v0,$a0,$a0 # return $a0 in $v0 suspicious ...?
lw $a0,0($sp) # restore the $a0
addi $sp,$sp,4 # put back the stack
jr $ra
一些问题
您在十进制测试期间销毁了$a0
值,因此它在十六进制部分的值是错误的
你的跳跃是在做[无限]循环。他们应该已经完成了:
我已经创建了两个版本的代码。一个带有注释,一个带有更正的代码[请原谅免费的样式清理]
以下是注释版本:
hexasc:
# NOTE/BUG: stack save/restore of $a0 is not needed due to MIPS ABI
addi $sp,$sp,-4 # make space on the stack
sw $a0,0($sp) # store $a0 on the stack
li $t0,0x30 # $t0 = 0x30 ('0' in ascii)
andi $a0,$a0,0xf # only 4 least significant bits is
# needed ignore other bits
# NOTE/BUG: altering $a0 further destroys the value for the hex test
loop:
add $a0,$a0,$t0 # $a0 i will think why i did this
addi $t0,$t0,1 # increment $t0 by 1
# NOTE/BUG: beq is wrong -- we want bgt
# NOTE/BUG: the range test for decimal should be 0x09 and _not_ 0x39
beq $t0,0x39,loop2 # if $t0 = 0x39 (9 in ascii)
# NOTE/BUG: looping is wrong -- this should be 'j done'
j loop
li $t1,0x41 # $t1 = 0x41 ( A in ascii)
# NOTE/BUG: $a0 is now wrong because of add above
loop2:
andi $a0,$a0,0xf # only 4 LSB ignore other bits
add $a0,$a0,$t1 # ???? i will think about this
# NOTE/BUG: no range check needed as all values are in range
beq $t1,0x46,done # if $t1 = 0x46 (F in ascii)
# NOTE/BUG: no looping required
j loop2
done:
add $v0,$a0,$a0 # return $a0 in $v0 suspicious ...?
lw $a0,0($sp) # restore the $a0
addi $sp,$sp,4 # put back the stack
jr $ra
hexasc:
andi $a0,$a0,0xf # only 4 least significant bits is needed
# check for decimal
li $v0,0x30 # set 0x30 ('0' in ascii)
ble $a0,0x09,hexasc_done # value in range 0x0-0x9? if yes, fly
li $v0,0x41 # set 0x41 ('A' in ascii)
hexasc_done:
add $v0,$v0,$a0 # convert value to ascii
jr $ra
以下是更正的版本:
hexasc:
# NOTE/BUG: stack save/restore of $a0 is not needed due to MIPS ABI
addi $sp,$sp,-4 # make space on the stack
sw $a0,0($sp) # store $a0 on the stack
li $t0,0x30 # $t0 = 0x30 ('0' in ascii)
andi $a0,$a0,0xf # only 4 least significant bits is
# needed ignore other bits
# NOTE/BUG: altering $a0 further destroys the value for the hex test
loop:
add $a0,$a0,$t0 # $a0 i will think why i did this
addi $t0,$t0,1 # increment $t0 by 1
# NOTE/BUG: beq is wrong -- we want bgt
# NOTE/BUG: the range test for decimal should be 0x09 and _not_ 0x39
beq $t0,0x39,loop2 # if $t0 = 0x39 (9 in ascii)
# NOTE/BUG: looping is wrong -- this should be 'j done'
j loop
li $t1,0x41 # $t1 = 0x41 ( A in ascii)
# NOTE/BUG: $a0 is now wrong because of add above
loop2:
andi $a0,$a0,0xf # only 4 LSB ignore other bits
add $a0,$a0,$t1 # ???? i will think about this
# NOTE/BUG: no range check needed as all values are in range
beq $t1,0x46,done # if $t1 = 0x46 (F in ascii)
# NOTE/BUG: no looping required
j loop2
done:
add $v0,$a0,$a0 # return $a0 in $v0 suspicious ...?
lw $a0,0($sp) # restore the $a0
addi $sp,$sp,4 # put back the stack
jr $ra
hexasc:
andi $a0,$a0,0xf # only 4 least significant bits is needed
# check for decimal
li $v0,0x30 # set 0x30 ('0' in ascii)
ble $a0,0x09,hexasc_done # value in range 0x0-0x9? if yes, fly
li $v0,0x41 # set 0x41 ('A' in ascii)
hexasc_done:
add $v0,$v0,$a0 # convert value to ascii
jr $ra
这两篇文章中有一个值得一提的小错误,
li$v0,0x41
应该是li$v0,0x7
。这是因为您指定输入值10
应以ASCII打印字符A
,但如果您有li$v0,0x41
,则输入值10
的输出将是K
,而不是A
。
这里是另一个版本的hexasc
,它可以打印出您的规范中所说的内容
hexasc:
andi $a0,$a0,0x0f
addi $v0,$zero,0x30
addi $t0,$zero,0x9
ble $a0,$t0,L1
nop
addi $v0,$v0,0x7
L1:
add $v0,$a0,$v0
jr $ra
nop
在模拟器中的
hexasc
上设置一个断点,然后单步执行该函数以找出它生成错误结果的原因。为什么在返回之前恢复a0
?(并将其存储在开始处)。IIRC根据MIPS调用约定,子例程可以修改参数值。加上a0
末尾应该包含返回值,所以将其恢复为原始值有点困难。。不幸的。。。无论如何,一定要尝试调试器(我没有阅读例程的主体,只是推/弹出序列让我咯咯笑)。(现在我看了一下主体……您可能只想删除它并在纸上写下所有0-15个值,然后在它们旁边写下所有ASCII目标值(48'0'
,49'1'
,…)然后盯着它们看5分钟。你通过包含代码注释来解释你的算法吗?否则我们无法确定问题是你做了错误的事情,还是你试图做正确的事情但失败了。第一个函数注释得很好,但第二个只是一堵代码墙。是的,请准确地用0到15显示图表一边是ascii值,另一边是ascii值。然后解释你的算法如何连接这些点。哦..实际上我错了..返回值在v0
中。你可以无害地恢复a0
所以..正如你所看到的,很容易错误地读取代码…使用调试器更好。。)(我仍然认为可以修改a0
,调用者不应该期望参数保持不变?)谢谢你的回答,这对我很有帮助。不客气。asm一开始可能会让人望而生畏,但它会变得更容易。顺便说一句,因为你对asm比较陌生,所以习惯上对一个好的答案表示感谢的方式是:投票/接受答案。请参阅: