あなたの予想は正しいが、実験結果の解釈は正しくない
$t2 は 0x0005550 になります。これは MIPS エミュレータで確認されています。
いいえ、これは正しくありません。したがって、次のいずれかです。
- どういうわけか、エミュレータが何をしているのかを誤解しています。エミュレータからの実際の値は、期待どおりです。
- または、想定どおりの前にありませんが
0x55555550
、代わりに (つまり) テストプログラムが正しくセットアップされていません。$t2
andi
0x5550
$t2
しかし、それは私が期待したものではありません。答えは 0x55555550 & 0xFFFFFFFF = 0x55555550 であるべきだと思います。and ロジックの前に、定数 -1 が 0xFFFFFFFF に符号拡張されたと思います。
はい、これは正しいです。そして、何が起こっているのか、そしてその理由を以下で説明します。
しかし、答えは 0x55555550 & 0x0000FFFF だったようです。-1 が 0xFFFFFFFF ではなく 0x0000FFFF に符号拡張される理由
そうではありませんでした。に符号拡張されました0xFFFFFFFF
。繰り返しますが、あなたは実験結果を間違って読んでいます [またはテスト プログラムにバグがあります]。
mips
シミュレーターとアセンブラーには疑似操作があります。
これらは、実際の物理的な命令として存在する場合と存在しない場合がある命令です。ただし、それらはアセンブラによって解釈され、一連の物理的/実際の命令が生成されます。
「純粋な」疑似操作の例はli
(「すぐにロード」) です。対応する命令はありませんが、通常はlui
, ori
(物理命令)の 2 つの命令シーケンスを生成します。
疑似操作を、、、、、などのアセンブラディレクティブと混同しないでください。.text
.data
.word
.eqv
一部の疑似演算は、実際の物理命令と重複する可能性があります。それがあなたの例で起こっていることです。
実際、アセンブラは任意の命令を疑似操作の可能性として調べます。単一の物理的な命令でインテントを満たすことができると判断する場合があります。そうでない場合は、1 ~ 3 命令シーケンスを生成し、そのシーケンスの一部として[予約済み]$at
レジスタ [これは] を使用できます。$1
でmars
、実際の実際の命令を確認するにBasic
は、ソース ウィンドウの列を参照してください。
私の答えを完全にするために、以下のすべてはトップコメントで始まります。
3 つのサンプル プログラムを作成しました。
addi
元の投稿のように
andi
修正された投稿のように
- 符号なし引数
andi
を使用する
(1)を使用した元の質問のアセンブラソースは次のaddi
とおりです。
.text
.globl main
main:
li $t2,0x55555550
addi $t3,$t2,-1
nop
mars
解釈方法は次のとおりです。
Address Code Basic Source
0x00400000 0x3c015555 lui $1,0x00005555 4 li $t2,0x55555550
0x00400004 0x342a5550 ori $10,$1,0x00005550
0x00400008 0x214bffff addi $11,$10,0xffffffff 5 addi $t3,$t2,-1
0x0040000c 0x00000000 nop 6 nop
addi
16ビット即時に符号拡張するので、0xFFFFFFFF
. 次に、2 の補数加算演算を実行すると、最終結果は次のようになります。0x5555554F
したがって、アセンブラは のために追加の命令を生成する必要がなかったaddi
ので、addi
疑似演算は単一の実数を生成しました。 addi
(2)andi
ソースは次のとおりです。
.text
.globl main
main:
li $t2,0x55555550
andi $t3,$t2,-1
nop
アセンブリは次のとおりです。
Address Code Basic Source
0x00400000 0x3c015555 lui $1,0x00005555 4 li $t2,0x55555550
0x00400004 0x342a5550 ori $10,$1,0x00005550
0x00400008 0x3c01ffff lui $1,0xffffffff 5 andi $t3,$t2,-1
0x0040000c 0x3421ffff ori $1,$1,0x0000ffff
0x00400010 0x01415824 and $11,$10,$1
0x00400014 0x00000000 nop 6 nop
うわあ!どうしたの?生成された 3 つのandi
命令。
実際の 命令andi
は、直接の引数を符号拡張しません。したがって、実数で使用できる符号なしandi
の最大値は次のとおりです。0xFFFF
しかし、 を指定することで、符号拡張が-1
必要であることをアセンブラに伝えました(つまり)0xFFFFFFFF
したがって、アセンブラは単一の命令で目的を達成できず、上記のシーケンスが得られます。そして、生成されたシーケンスは使用できませんでしandi
たが、登録フォームを使用する必要がありました: and
. 以下は、andi
生成されたコードをより使いやすい asm ソースに変換したものです。
lui $at,0xFFFF
ori $at,$at,0xFFFF
and $t3,$t2,$at
結果として、私たちはアンドを行っており0x55555550
、0xFFFFFFFF
これは [まだ変更されていない] の値です0x55555550
(3) の無署名バージョンのソースは次のandi
とおりです。
.text
.globl main
main:
li $t2,0x55555550
andi $t3,$t2,0xFFFF
nop
アセンブラの出力は次のとおりです。
Address Code Basic Source
0x00400000 0x3c015555 lui $1,0x00005555 4 li $t2,0x55555550
0x00400004 0x342a5550 ori $10,$1,0x00005550
0x00400008 0x314bffff andi $11,$10,0x0000ffff 5 andi $t3,$t2,0xFFFF
0x0040000c 0x00000000 nop 6 nop
アセンブラは、16 進数の定数 (つまり、プレフィックス) を使用していることを認識すると、値を符号なし0x
操作として実行しようとします。したがって、拡張に署名する必要はありません。そして、本物はその要求を満たすことができます。andi
この結果は0x5550
のマスク値を使用した場合0x1FFFF
、それは符号なしになることに注意してください。ただし、これは 16 ビットより大きいため、アセンブラは要求を満たすために複数命令シーケンスを生成します。
そして、ここでの結果は0x15550