2017-10-23 13 views
0

したがって、最初の文字が数字以外の数字で、残りが数字の文字列をユーザーから受け取るコードを記述しました。私のコードは、最初の文字を削除し、残りの数値を変数に格納します。残りの数字に定数(例5)を加えて印刷してみようとしています。何がうまくいかないのか分かりません。MIPSは、そのアドレスの値の代わりにアドレスを出力します。

.data 

    string: .asciiz  "Enter a string:\n" 
    string1: .asciiz   "The value +5 is:\n" 
    inputString: .space 20 
    outInt: .word 0 
    int5: .word 5 
    addedInt: .word 0 


.text 

main: 

    #print initial string to console insruction 4 
    li $v0, 4 
    la $a0, string 
    syscall 

    #get first string from user 
    li $v0, 8 
    la $a0, inputString 
    li $a1, 8  #a1 contains max length of string to be entered 
    la $t0, ($a0) 
    syscall 

    addiu $t0, $t0, 1 #remove first letter 

    li $v0, 4  #prints out remaining numbers without leading character 
    la $a0, ($t0) 
    syscall 

    sw $a0, outInt #store new word in outInt 


    lw $t0, outInt #print out outInt to check if its correct 
    la $a0, ($t0) 
    syscall 

    lw $t1, int5 
    add $t2, $t0, $t1 #add 5 to the remaining numbers 

    sw $t2, addedInt #store result 
    li $v0, 4 
    la $a0, string1 #print the value + 5 string 
    syscall 

    li $v0, 1 #output a number (not a string) 
    lw $a0, addedInt 


    syscall 

    jr $ra 

私は、文字列を入力し、出力 "X123" は次のとおりです。

は、文字列を入力します。

X123

値を+5 :

あなたのコードは何
+0

出力は何ですか?その理由は何ですか? –

+0

出力は128でなければなりません(123 + 5 = 128であるため)。それは割り当てのためです。 –

+0

デバッガを使用してコードをシングルステップ実行すると、レジスタには何が表示されますか? –

答えて

0

:(あなたは、実行時に取得するようにまったく同じ割り当てに見えるMARS下268501027であることを起こる、)アドレスinputStringで20バイトのメモリバッファに

入力文字列を。

ユーザが「X123」と入力すると、メモリ内のバイトは58 31 32 33 0A 00 00 00 ...のようになります(MARSの1バイトあたりのメモリの表示方法がわからないため、リトルエンディアンの動作を理解する必要があります。 MARSに表示される単語の値がどのように特定の1バイトに分解されるか)、0x58は文字XのASCIIコード、0x31は文字/数字1のASCIIコードなどです。0x0Aは改行文字(入力の一部です)残りのゼロはあなたの運となり、MARSはコードの実行開始時にゼロの.dataセグメントを提供するので、次のユーザーストリングの出力は正しくゼロ終端されます(改行も行います)。

そして桁'1'ためにその0x31 = ASCIIコードを指し示すアドレスinputString+1からあなた出力ストリング、およびユーザ入力の残りは、このように予想される(?)文字列「123 \ n」が出力され、続きます。 「最初の文字を削除する」とはマシンから何も削除しないで、ポインタを調整するだけです。ポインタは文字列の「開始」として使用されます。同じメモリ空間内の文字を本当に削除するには、すべての文字を1バイトずつ前のアドレスにコピーする必要があります。これははるかにコストのかかる操作で、1つずつポインタを調整します。

sw $a0, outInt  #store new word in outInt 

アドレスoutIntのメモリワードにアドレス268501028を調整この店舗。単語自体は保存されません。文字列のintへの変換もここでは起こりません。あなたがすべてが、以前の値4が再使用されているので、あなたは再び出力文字列に、明示的v0引数を記述することなく、次のsyscallを呼び出す32B符号なし整数である、ちょうどポインタ(メモリアドレス)を格納268501028.

です同じアドレスから同じ出力を得ます。"123\n"。すでに登録されているのと同じ値であっても、の前に常にv0を明示的に設定することをお勧めします。先頭へのデバッグとレビュー時のソースの読み込みを容易にします。

最後に、あなたはt1に値5をロードし、アドレスaddedIntにメモリに整数268501033になり、そのアドレス268501028にそれを追加し、それを格納します。次に、+5ラベルを印刷し、その値をa0に戻して印刷します。

使用しているMARS/SPIMファミリシミュレータのデバッガを使用して命令をシングルステップ実行し、レジスタ値+メモリ内容を監視して説明と比較して、実際にそれらの命令を完全に把握する必要があります行う。

修正:

「広すぎる」、基本的には次のものが必要、次のいずれか

a)の整数値にユーザーが文字列に変換する:あなたは改行文字またはゼロターミネータのどちらかに到達するまで、文字入力による負荷手紙を数字の文字を値(ASCII_code - '0') == digit_valueに変換し、で始まるsum = sum*10 + digit_valueという一時的な合計を計算します。ループの最後に、sumには値123(文字列"123")が含まれます。次に、整数として(値が128)を追加し、syscall, v0=1を使用して出力することができます。

b)文字列の上に値5を追加する、つまり改行/ゼロターミネータのアドレスを見つけ、最後に1を戻す(入力が有効な場合は! inputStringにアドレスを設定し、アドレスが有効な場合は、範囲'0' = 0x30 .. '9' = 0x39の内容をチェックすることもできます。つまり、内容はASCIIの桁数字です:1)現在の文字に5を追加する2)結果が<= '9'文字列は数字のように見え、それを出力することができます(表示にはinputString+1アドレスで出力への分岐)。 3)それから10を引く(すなわち、'7'+5 = 60 = '<'、次に60 - 10 = 50 = digit-letter '2')4)アドレスを1減らす(1つ左に移動する)。5)アドレスを検証する。 6)内容をチェックする:数字でない場合は、文字'1'で上書きし、その'1'の出力にジャンプする("X99"のような有効な入力はinputStringと等しくなり、メモリには変更された文字列"104"が含まれる)それに1を加え、ステップ2にジャンプします) - 結果の値が<= '9'であるかどうかを確認します。

整数値以上ではなくメモリ上のASCII文字を操作するときは「5を加算する」ということです。多くの作業のように聞こえるかもしれませんが、変種a)の変換文字列からintよりも+ debugを書く方が実際に簡単です。

最終的には、アセンブリーでの基本データ型の仕組みを理解し、 "文字列"と整数値(およびバイトとワード値)の違いとメモリアドレス指定の仕組みを理解するために、 。

関連する問題