私はこれを理解するために壁に頭をぶつけてきました、そしてこれは私には意味がありません...
このプログラムが無限ループに入るのはなぜですか?!
ここtest
に示すように、2つの値を比較して等しいと思いました...なぜ機能しないのですか?
int main()
{
__asm
{
mov EAX, 1;
mov EDX, EAX;
test EAX, EDX;
L: jne L;
}
}
命令が何をするかについてのあなたの期待TEST
は間違っています。
この命令は、ビット テストを実行するために使用されます。通常、マスクを指定して特定のビットが設定されているかどうかを「テスト」するために使用します。JZ
これは(jump if zero) またはJNZ
(jump if not zero) 命令と組み合わせて使用されます。
このテストでは、2 つのオペランドに対してビットごとの AND を実行し、適切なフラグを設定します (結果を破棄します)。マスク内の対応するビットが設定されていない場合、ZF (ゼロ フラグ) は1
(すべてのビットがゼロ) になります。設定されているかどうかをテストしたい場合は、JNZ
命令を使用します。何も設定されていないかどうかをテストしたい場合は、JZ
命令を使用します。
JE
とはJNE
、フラグの解釈が異なるため、この命令には適していません。
いくつかの変数に対して等価性チェックを実行しようとしています。命令を使用する必要がありCMP
ます。通常、値を相互に比較するために使用します。
比較では、オペランドが効果的に減算され、フラグのみが設定されます (結果は破棄されます)。等しい場合、2 つの値の差は0
(ZF = 1) です。等しくない場合、2 つの値の差はゼロではありません (ZF = 0)。それらが等しいかどうかをテストしたい場合は、JE
(jump if equal) 命令を使用します。それらが等しくないかどうかをテストしたい場合は、JNE
(等しくない場合はジャンプ) 命令を使用します。
この場合、 を使用TEST
したため、結果のフラグはZF = 0
(0x1 & 0x1 = 0x1、ゼロ以外) になります。であるため、ここに表示されているようZF = 0
に、JNE
命令は分岐します。
CMP
値ではなく等しいかどうかをチェックする場合は、命令を使用して値を比較する必要がありTEST
ます。
int main()
{
__asm
{
mov EAX, 1
mov EDX, EAX
cmp EAX, EDX
L: jne L ; no more infinite loop
}
}
これを読むだけで(私のasmは非常に錆びています)そしてこれ
JNEはZF(ゼロフラグ)にジャンプします= 0
TESTはZF=0を設定します。ビット単位のEAXANDEDXの結果が1の場合、ビット単位のANDの結果が0の場合は1になります。
ANDの結果が0の場合、ZFは1に設定され、それ以外の場合は0に設定されます。
したがって、ZFで1AND1の結果が0になるとジャンプします。
論理的でありながら直感に反しているようです。
@ A.Webbは正しいと思います-ゼロフラグを設定するためにbitwuse操作の動作に依存しているため、TEST命令を使用している場合は、おそらくJNZであるはずですが、SUB命令は必要に応じてゼロフラグを設定します。
これは非常に簡単です。命令が何をするのか、命令が読み書きするプロセッサの状態を知る必要があることは明らかです。疑問がある場合は、リファレンス マニュアルを入手してください。Intel x86 のマニュアルは、オンラインで簡単に見つけることができます。
あなたの特定のプログラム:
mov EAX, 1;
定数 1 を EAX に移動します。他の状態変化は発生しません。
mov EDX, EAX;
EAX のコンテキストを EDX にコピーするため、値 1 も含まれます。
test EAX, EDX;
test は、2 つのレジスタのビットごとの AND を計算し (リファレンス マニュアルを確認しましたか?)、答えを破棄し、答えに基づいて条件コード ビットを設定します。あなたの場合、各レジスタの上位31ビットはゼロであり、ゼロを生成します。最下位ビットは両方のレジスタで 1 です。and'd は 1 を生成します。最終的な効果は、32 個のバイナリ値「1」が生成され、条件コード ビットが設定された後に破棄されることです。このプログラムで重要な条件コード ビットが 1 つあります。それは「Z」(ero) ビットで、最後の条件コード設定操作で完全なゼロ値が生成された場合に設定されます。このテストで「1」が生成されたので、Z ビットがリセットされます。他の条件コード ビットを調べさせていただきます。
L: jne L;
これは「等しくない場合のジャンプ」です。たとえば、Z ビットがリセットされた場合にジャンプします。あなたのプログラムでは、Z がリセットされ、jmp が発生します。実行後、プロセッサは同じ命令にあり、別の命令 (同じ jmp) を認識します。条件コード ビットは、jmp 命令によって変更されません。
ということで・・・無限ループに陥ります。
アセンブラがサポートするさまざまなオペコードには、多くの同義語があります。たとえば、「JZ」と「JE」は同じ命令の同義語です。同義語を混同しないでください。