1

MARS シミュレーターを使用して、MIPS 言語で 2 進数を 10 進数に変換しようとしています。このプログラムは 2 進数を受け入れ、乗算 (数値の桁 $t9 だけ左にシフト) によって変換を行います。別の言い方をすると、各 1 桁に 2 の累乗をかけ、その結果を合計します。

ascii と 10 進数の間で値がどのように格納され、伝達されるかについてよく理解していません。問題は、「合計」が 10 進数の 2 進数の値ではなく 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

$t91 つの問題は、反復ごとに 2 回減少していることです。最初のデクリメント (48 を引いたもの) はそのままにして、他の 2 つを削除する必要があります。

もう 1 つの問題は、文字列を左から右に解析する場合、ある時点で文字列の長さを考慮する必要があることです。理想的に$t9は、文字列の長さを 0 ではなく ( の後の 2 行目startConvert) に設定しますが、文字列の長さはまだわかっていません。

1 つのオプションは、事前に文字列を解析して長さを決定し、$t9その値に設定することです。

より洗練された方法は、1 回のパスですべてを実行することです。文字列の長さは、区切り文字を含めて 16 文字であると想定します (したがって、最初に割り当て16ます$t9)。文字列が実際には 5 文字の長さであるとします。次に、ループの後、合計が の係数で高すぎます2^(16-5) = 2^11。しかし、 の最終値が であることに注意して$t9ください11$t9そのため、合計レジスタを多くのビットだけ右にシフトすることで、エラーを修正できます。

最後に、MARS は0x0A文字列の最後に (これは Enter キーを押すことによるものです) の文字を入れているようです (ただし、15 文字すべてを使用する場合を除きます。0x00代わりに使用します。 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 に答える