2017-10-14 10 views
0

ユーザーはどの温度にいるかを尋ね、その入力を受け取り、4つの温度を変換して出力するプログラムを作成しています。私は私のブランチ、beqで動作するように私のユーザーの読み込みを取得する助けが必要です。私は格納されたバージョンと同じように入力 'f'を再認識することができません。入力された文字列と格納された文字列を比較する方法-MIPS

.data  
temptype: .asciiz "Enter temperature type i.e. f, c, k, r: " 
tempdegree: .asciiz "\n Enter degrees: " 
space: .space 2 
tempx: .asciiz "Your temperature in celsius is: " 
tempc: .asciiz "\nYour temperature in celsius is: " 
tempf: .asciiz "\nYour temperature in fahrenheit is: " 
tempk: .asciiz "\nYour temperature in kelvin is: " 
tempr: .asciiz "\nYour temperature in rankine is: :" 
kr: .float 459.67 

.globl main 

.text 
    main: 

     li $v0, 4 
     la $a0, temptype 
     syscall 

     li $v0, 8 
     la $a0, space 
     #li $a1, 2 
     move $t0, $a0 
     syscall 

     li $t1, 102 
     #li $t1, 99 
     #li $t1, 107 
     #li $t1, 114 
     syscall 

     beq $t0, $t1, fahrenheit 
     #beq $t0, $t1, celsius 
     #beq $t0, $t1, kelvin 
     #beq $t0, $t1, rankine 
     syscall 

     li $v0,10 
     syscall 

    fahrenheit: 

     li $v0, 4 
     la $a0, tempdegree 
     syscall 

     li $v0, 5 
     syscall 

     move $t0, $v0 

     li $v0, 4 
     la $a0, tempf 
     syscall 

     move $a0, $t0 
     li $v0, 1 
     syscall 
+1

組み込みデバッガでコードをシングルステップ実行しましたか?あなたがレジスタ内の文字を返すかどうか、またはそれをメモリに格納するかどうかを確認するために使っているシステムコールについて、ドキュメントをチェックしましたか?あなたは数字や何かに対してポインタを比較しているかもしれません。 (あなたはあなたのコードをコメントしていないし、私は頭の上からMIPSシミュレータのシステム番号を知りません。)とにかく**デバッガ**を使うと、 'beq'が見ている各レジスタに実際に何が入っているかを確認するのがずっと簡単になります。 –

答えて

3

MIPS CPU(および他の一般的なもののいずれも)は、「文字列を比較する」命令を持っていない、文字列は、CPUのネイティブ型ではなく、命令が言葉やバイトのように、ネイティブ型でのみ取り扱います。

"文字列"は、連続する文字のある量(どこかで定義されているか、データの最後にターミネータ文字を使用しています)です。 "1文字"とは、使用されているエンコーディングに依存します(MARSシミュレータ、およびASMプログラミングの簡単な練習).1文字が正確に1バイトである古いASCIIエンコーディングに固執することができます。 (JFYI:現代のSWでは、ほとんどの場合UTF8エンコーディングで動作します。このWebページのように、1文字にエンコードするグリフに応じて異なるバイト数を持つことができます。これにより、UTF8でエンコードされた文字列アルゴリズムを)あなたの現在の仕事よりも、かなり頻繁に楽しいです。)

CPUレジスタは「ワード」サイズであるため、32ビット「ワイド」です。すなわち、一度に最大4つのASCII文字を保持できます4バイト)ので、レジスタを使用して文字列全体を格納すると、非常に簡単にしか使用できません。 str。それ以外はnothです。あなたはそれを行うことができますが、beqが有効な場合を除き、単語値0x30303030 = "0000"0x31313131 = "1111"beqと比較することができます。

ほとんどの場合、MIPS初心者のアセンブリでプログラミングしている間、 "文字列"は次のようなパターンになります:レジスタには最初の文字列(文字列の最初のバイト)を指すメモリアドレスと、文字列は文字ではありませんが、値のゼロはいわゆる "ヌルターミネータ"です。

文字列を比較する場合、2つのポインタ(2つの文字列= 2つの最初の文字)で始まるループを作成します。両方のアドレスからある一時的なレジスタにバイトをロードする(つまり両方の最初の文字をロードする)、比較する。等しい場合は、ゼロをチェックします(両方の文字列が終了している=等しい)。ゼロでない場合は、両方のアドレスを1つ進めて、次の文字を指し、先頭にループします。

あなたのケースでは、ユーザーは1文字だけを入力することができ、1文字のみを比較したいので、ループ全体を書くことは多大な労力を要します。だから、上からソースを読ん

、これらの行は、私のコメントを取得します:

#li $a1, 2 

はなぜコメントアウトされて?あなたはそれを使ってシステムコールを制限しなければなりません(私は何も設定せずに、デフォルト値がゼロかもしれないので、入力はありません)。また、あなたは興味があるかもしれませんsyscall(v0=12) "読み込み文字列"の代わりに "文字を読む"が、私はどのようにMARS(ユーザーエクスペリエンス関連)のユーザーに提示されているのかわかりませんが、サービスv0 = 8 "読み取り文字列" 2バイトの長さのバッファ。

syscallが返された後(ユーザが文字 "f"を入力した)、アドレスspaceのメモリには、syscall:102,0で設定された2バイトが含まれます。

li $t1, 102 

馴染みますが、MARSアセンブラであなたも、その番号を書いて、このように使用することができ、他のプログラマのための読み取りが困難になります。li $t1, 'f'を - シンプルなアポストロフィがアセンブラに指示します、あなたは、単一のASCII文字の値が欲しい('ab'がエラーでありますMARSで、ただ一つの文字を使用することができ、他のいくつかのアセンブラは、2つのバイト値として「AB」を翻訳することができる)

次のコメントを外し命令は次のとおりです。

あなたはどのMAを求めている
syscall 

そして、ここにRSサービス? v0に値を設定しておらず、サービスも必要ないので、デバッガでコードを一歩進んだりする場合は、各命令で何が起こっているのかがわかれば、意味をなさないはずです。

次に、beq $t0, $t1, fahrenheitとなります。その時点で

t1'f'に等しく、t0、そのバッファの最初のバイトのアドレスに等しく、また0x100000cようなものとおそらく同様に、いくつかの32ビット値に等しい、コンパイル時spaceシンボルとしてエイリアス。値0x100000c102は必ずしも等しくないので、beqは決してfahrenheitというラベルにジャンプしません。 (高度情報最初の負荷がt0のアドレスから値をバイトこと、lb $t2, ($t0)ように、メモリから値をフェッチバッファ内のその最初の文字を比較する

lbは32ビット値に8ビット値を、符号拡張されます基本的な印刷可能ASCIIの文字はすべて128より小さいので、負の値を扱う必要はありませんが、文字 'f'が140としてエンコードされる場合、t2にその値をロードするためにlbを使用すると、140ではなく、32ビットの値-116が生成されます。私が書いたように、基本的なASCIIはわずか7ビットなので、期待通りに動作する正の値のみが102としてロードされます)。

beq $t2, $t1, fahrenheitで成功すれば、ASCII文字とASCII文字を比較できるようになります。

また、MARS MIPSアセンブリ疑似命令beq $t2, 'f', fahrenheitを使用することもできます。限り、あなただけのためにソースコードを短くするために開始します一度(読みながら、それは理にかなっているように、あなたのプログラミングでは良いですいくつかのタイピングを、保存

addi $at, $zero, 102 # 102 = 'f', $at = $1, $zero = $0 
beq $at, $t2, fahrenheit 

:MARSは、2つのネイティブ命令としてそれをコンパイルします。あなたがそれを間違ってやっている、ソースコードのプログラミングでは、読んでいると書かれている、書き込みコストは読書コストに比べて無視できる)です。この場合、beq $t2, 'f', labelは私にはかなり読めるように見えるので、私はそれを好むでしょう。

これは、あなたの質問、明示的なもの(文字列を文字列で比較する方法)、暗黙のもの(両方の文字を 'f'と比較する方法) )。

+0

マイナーなquibble:x86には 'repeat cmpsb'があります。これは文字列を比較し、x86はかなり一般的です。文字列を比較するのが最高のパフォーマンスではないことがよくあります。そうでなければ、文字列の長さを知っていなければなりません。 stos/movs/lods/cmps/scasは文字列命令と呼ばれます。 –

+0

@PeterCordes fair quibble ...しかし、この質問とOPの期待される技術レベルの文脈では、私はここでコメントをコメントに残しておくのが最善であると思いますが、私は既に免責事項で括弧に余分な情報を入れようとしました。 OPがTLDRのようなものであることを幾分心配しています.... OP:もしTLDRならば、ここに要約があります:**デバッガを使用してください** – Ped7g

+0

@ Ped7gありがとう!私はそれを働かせた。あなたの反応は非常に参考になりました。 –

関連する問題