0

文字列を受け取り、結果を文字のみで出力するプログラムを MIPS で作成しようとしました (文字列が英数字であると仮定します)。サイズが 4 未満の文字列では完全に機能しますが、4 番目の文字が発生すると、無限ループに入ります。

.data
    string: .word 10
.data
    result: .word 10
.data
    message1: .asciiz "number\n"
.data
    message2: .asciiz "letter "
.data
    message3: .asciiz "finished loop\n"


.text
    main:
        li $v0 8    # take input as string
        la $a0 string   # store it in "string"
        la $a1 10   # size of "string" is at most 10
        syscall
        la $s0 string   # save address of "string" to s0
        la $s1 result   # save address of "result" to s1


        Loop:
            li $t0 10   # set t0 as '/n'
            lb $t1 ($s0)    # load character that we are currently checking
            beq $t0 $t1 Exit    # check if we are at the end of the string


            li $t0 64   # set t0 to 64 to check if it is a letter (character that we are now checking must be greater than 64)
            slt $t2 $t0 $t1 # t2 will store the result of comparison ($t1 - character)
            li $t0 0    # set t0 to 0 to check the result of comparison
            beq $t2 $t0 Increment # if 64 > ch, then we must just proceed
            li $v0 4
            la $a0 message2 # print message that it is a character
            syscall
            sb $t1 ($s1)    # copy this character into our "result"
            addi $s1 $s1 1  # increment the address of "result"

        Increment:
            li $v0 4
            la $a0 message1 # print message that it is a number
            syscall
            addi $s0 $s0 1  # increment the address of "string" to proceed in loop
            j Loop

        Exit:
            li $t0 10
            sb $t0 ($s1)    # add endline character to "result"
            addi $s1 $s1 1
            li $t0 0
            sb $t0 ($s1)    # add null character to "result"
            li $v0 4
            la $a0 message3 # print message that the loop has finished
            syscall
            li $v0 4
            la $a0 result   # print result
            syscall
            jr $ra

前もって感謝します。

4

1 に答える 1

1

自分で踏み出さないとわかりにくいですが、ここにアイデアがあります。「i」の力、つまり即時モードを使用します。そうすれば、レジスタの値が期待どおりではないかどうかを心配する必要がなくなります。また、レジスターにゼロをロードする代わりに、特殊$zeroレジスターを使用してください。したがって、これを変更します。

        li $t0 64   # set t0 to 64 to check if it is a letter (character that we are now checking must be greater than 64)
        slt $t2 $t0 $t1 # t2 will store the result of comparison ($t1 - character)
        li $t0 0    # set t0 to 0 to check the result of comparison
        beq $t2 $t0 Increment # if 64 > ch, then we must just proceed

これに:

        slti $t2, $t1, 'A' # A little different: set $t2 if $t1 < 65 ('A')
        bne $t2, $zero Increment # branch if $t1 < 'A'

おそらく、即値を優先してレジスタを削除することで、ループに陥る原因となっているグリッチを見つけることができます。

また、考えられるその他のグリッチの原因は次のとおりです。

  • 文字列を終了しようと'\n'していますが、入力が完全な 10 文字の場合にシステムコールが \n を追加することを保証できるかどうかはわかりません。おそらく、ゼロターミネータのバイト値も/代わりにチェックする必要があります。

  • stringandを 10 ワードとして定義しましresultたが、実際にはバイトを格納しています。それは問題にはなりません - 10 バイトではなく 40 バイトを割り当てbyteまし\0\n

申し訳ありませんが、具体的には言えませんが、正しい方向に向けていただければ幸いです。

于 2013-11-07T17:04:34.450 に答える