在 MIPS 中编写将整数 0 到 15 转换为 ASCII 字符的子例程,'0'到 'F'



编写一个小子程序,将0到15之间的数字转换为可打印的ASCII编码字符:"0"到"9",或"A"到"F",具体取决于数字。对于不在0到15范围内的数字,一些位将被忽略。

名称:子例程必须称为hexasc。参数:一,在寄存器$a0中。4个最低有效位指定一个数字,从0到15。寄存器$a0中的所有其他位可以有任何值,必须忽略。返回值:寄存器$v0中的7个最低有效位必须是ASCII码,如下所述。当函数返回时,所有其他位必须为零。必需操作:函数必须将0到9的输入值转换为数字的ASCII代码分别为"0"到"9"。输入值10到15必须转换为字母"A"到"F"。

.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子程序,由于某种原因,我不理解,所以它不起作用。我不知道我在哪一部分有错误,也许我没有按照上面规范中的Say做。如有任何帮助,我们将不胜感激。

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

这两篇文章中有一个小错误值得一提,li $v0,0x41应该是li $v0,0x7。这是因为您指定10的输入值应该以ASCII打印字符A,但如果您有li $v0,0x41,则10的输入值的输出将是K而不是A。这是hexasc的另一个版本,它可以打印出你规范中的Say’s。

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

一些问题。。。

您在十进制测试期间销毁了$a0值,因此它的十六进制部分的值错误。

你的跳跃是在做无限循环。他们应该去done:

我已经创建了您代码的两个版本。一个带有注释,一个带有更正的代码[请原谅免费的样式清理]。

这是注释版本:

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

最新更新