1

我正在尝试使用 MARS 模拟器将 MIPS 语言中的二进制转换为十进制。程序接受一个二进制数,然后通过乘法进行转换(左移数字的位置 $t9)。另一种说法是将每个 1 位数字乘以 2 乘以该位的幂,然后将结果相加。

我对值如何在 ascii、十进制之间存储和通信并没有很好的理解,问题是“总和”是 40,000,而不是十进制二进制数的值。我在这里做错了什么?

 .data
  msg1:
    .asciiz "Enter a number in base 2 (-2 to quit): "
  msg2:
    .asciiz "\nResult: "
  allOnes:
    .asciiz "1111111111111111"
  empty:
    .space 16
  newLine:
    .asciiz "\n"
  sum:
    .space 16 
  sumMsg:
    .asciiz "\nSUM: "
  oneFound:
    .asciiz "\nOne found\n"
  zeroFound:
     .asciiz "\nZero found\n"
.text
.globl main
main:

getNum:
li $v0,4        # Print string system call
la $a0,msg1         #"Please insert value (A > 0) : "
syscall

la $a0, empty
li $a1, 16              # load 16 as max length to read into $a1
li $v0,8                # 8 is string system call
syscall

la $a0, empty
li $v0, 4               # print string
syscall

li $t4, 0               # initialize sum to 0

startConvert:
  la $t1, empty
  li $t9, 16                # initialize counter to 16

firstByte:
  lb $a0, ($t1)      # load the first byte
  blt $a0, 48, printSum 
  addi $t1, $t1, 1          # increment offset
  subi $a0, $a0, 48         # subtract 48 to convert to int value
  beq $a0, 0, isZero
  beq $a0, 1, isOne
  j convert     # 

isZero:
   subi $t9, $t9, 1 # decrement counter
   j firstByte

 isOne:                   # do 2^counter 
   li $t8, 1               # load 1
   sllv $t5, $t8, $t9    # shift left by counter = 1 * 2^counter, store in $t5
   add $t4, $t4, $t5         # add sum to previous sum 

   move $a0, $t4        # load sum
   li $v0, 1              # print int
   syscall
   subi $t9, $t9, 1 # decrement counter
   j firstByte

convert:

printSum:
   srlv $t4, $t4, $t9
   la $a0, sumMsg
   li $v0, 4
   syscall

 move $a0, $t4      # load sum
 li $v0, 1      # print int
 syscall

exit:
   li $v0, 10       # exit system call
   syscall
4

1 回答 1

5

一个问题是您$t9每次迭代都会递减两次。您应该将第一个减量(减去 48 后的那个)保留在原处,并删除另外两个。

另一个问题是,如果您从左到右解析字符串,那么您需要在某些时候考虑字符串的长度。理想情况下,您将设置$t9为字符串的长度而不是 0(在 之后的第二行startConvert),但我们还不知道字符串的长度。

一种选择是预先解析字符串以确定其长度,并设置$t9为该值。

一种更优雅的方法是一次性完成所有操作:假设字符串长度为 16 个字符,包括分隔符(因此,分配16$t9第一个)。假设字符串实际上是 5 个字符长。然后在你的循环之后,总和将太高一个因子2^(16-5) = 2^11$t9但请注意的最终值为11。因此,您可以通过将和寄存器向右移动$t9许多位来修复错误。

最后,看起来 MARS 将一个字符0x0A(这是按 Enter 键)放在字符串的末尾(除非您使用所有 15 个字符;然后它使用它0x00,因为它会在第 15 个字符之后自动停止,然后再给您有机会按 Enter 键)。所以就beqz行了,而不是比较0,而是检查 if $a0 < 48。这将处理这两种情况,无论分隔符是0x00还是0x0A


这是我的修复版本:

.data
  msg1:
    .asciiz "Enter a number in base 2 (-2 to quit): "
  msg2:
    .asciiz "\nResult: "
  allOnes:
    .asciiz "1111111111111111"
  empty:
    .space 16
  newLine:
    .asciiz "\n"
  sum:
    .space 16 
  sumMsg:
    .asciiz "\nSUM: "
  oneFound:
    .asciiz "\nOne found\n"
  zeroFound:
     .asciiz "\nZero found\n"
.text
.globl main
main:

getNum:
li $v0,4        # Print string system call
la $a0,msg1         #"Please insert value (A > 0) : "
syscall

la $a0, empty
li $a1, 16              # load 16 as max length to read into $a1
li $v0,8                # 8 is string system call
syscall

la $a0, empty
li $v0, 4               # print string
syscall

li $t4, 0               # initialize sum to 0

startConvert:
  la $t1, empty
  li $t9, 16             # initialize counter to 16

firstByte:
  lb $a0, ($t1)      # load the first byte
  blt $a0, 48, printSum    # I don't think this line works 
  addi $t1, $t1, 1          # increment offset
  subi $a0, $a0, 48         # subtract 48 to convert to int value
  subi $t9, $t9, 1          # decrement counter
  beq $a0, 0, isZero
  beq $a0, 1, isOne
  j convert     # 

isZero:
   j firstByte

 isOne:                   # do 2^counter 
   li $t8, 1               # load 1
   sllv $t5, $t8, $t9    # shift left by counter = 1 * 2^counter, store in $t5
   add $t4, $t4, $t5         # add sum to previous sum 

   move $a0, $t4        # load sum
   li $v0, 1              # print int
   syscall
   j firstByte

convert:

printSum:
   srlv $t4, $t4, $t9

   la $a0, sumMsg
   li $v0, 4
   syscall

 move $a0, $t4      # load sum
 li $v0, 1      # print int
 syscall

exit:
   li $v0, 10       # exit system call
   syscall
于 2014-04-25T05:19:38.413 回答