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