可能性のある複製:
x86アセンブリ-'testl' eaxに対するeax?
私はアセンブリ言語プログラミングを始めたばかりで、現在、バイナリから生成されたアセンブリ言語を読み込もうとしています。私は出会った
test %eax,%eax
またはtest %rdi, %rdi
などなど。これが何をするかについて私は非常に混乱しています。 %eax, %eax
の値は同じではありませんか?テストとは何ですか? AND
操作を実行していることをどこかで読みましたが、それらは同じ値なので、単に%eax
を返しませんか?
以下は、この使用法を見つけた1つのインスタンスです。
400e6e: 85 c0 test %eax,%eax
400e70: 74 05 je 400e77 <phase_1+0x23>
比較される2つの値が等しい場合はje
がジャンプすると思った......まあ、それは%eax
自体がよく、どのような状況でジャンプしないのか?
私は一般的にプログラミングの初心者なので、誰かがこれを説明してくれたらとても感謝しています。ありがとう!
CMP
はオペランドを減算し、フラグを設定します。つまり、差がゼロ(オペランドが等しい)の場合、ゼロフラグを設定します。
TEST
は、AND演算の結果がゼロの場合、ゼロ変数ZF
を設定します。 2つのオペランドが等しい場合、両方がゼロの場合、ビット単位のANDはゼロになります。 TEST
は、結果で最上位ビットが設定されている場合は符号フラグSF
を設定し、設定ビット数が偶数の場合はパリティフラグPF
も設定します。
JE
[Jump if Equals]は、ゼロフラグをテストし、フラグが設定されている場合にジャンプします。 JE
はJZ
[ゼロの場合ジャンプ]のエイリアスなので、逆アセンブラーはオペコードに基づいて1つを選択できません。 JE
は、CMP
の引数が等しい場合にゼロフラグが設定されるため、そのような名前が付けられます。
そう、
TEST %eax, %eax
JE 400e77 <phase_1+0x23>
%eax
がゼロの場合ジャンプします。
一部のx86命令は、オペランド(レジスタ)の内容をそのままにして、ゼロフラグ(ZF)などの特定の内部CPUフラグを設定/設定解除するように設計されています。 ZFでは、CPU内に存在するtrue/falseブールフラグと考えることができます。
この特定の場合、TEST命令はビット単位の論理ANDを実行し、実際の結果を破棄し、論理の結果に従ってZFを設定/設定解除します。結果がゼロの場合、ZF = 1に設定します。 ZF = 0に設定します。
JEのような条件付きジャンプ命令は、ジャンプ/非ジャンプのZFを調べるように設計されているため、TESTとJEを一緒に使用することは、特定のレジスタの値に基づいて条件付きジャンプを実行することと同等です:
例:
テストEAX、EAX
JE some_address
ZF = 1の場合にのみ、つまりAND(EAX、EAX)= 0の場合にのみ、CPUは「some_address」にジャンプします。これは、EAX == 0の場合にのみ発生します。
同等のCコードは次のとおりです。
if(eax == 0)
{
goto some_address
}
これは、EAX
がゼロかどうかを確認します。命令test
は、引数間でビットごとにAND
を実行し、EAX
にゼロが含まれる場合、結果はZFまたはZeroFlagを設定します。
test
が2つのオペランドを「and」しているのは正しいです。しかし、結果は破棄され、残っているのは重要な部分だけであり、フラグのみです。これらは設定されており、それがtest
命令が使用される(そして存在する)理由です。
JE
は、等しくない場合(前の命令が比較であった場合に意味を持ちます)、実際に何をするかではなく、ZF
フラグが設定されている場合にジャンプします。また、test
によって設定されるフラグの1つであるため、この命令シーケンス(テストx、x; je ...)には、xが0のときにジャンプするという意味があります。
このような質問(および詳細)については、x86命令に関する本をお勧めします。本当に大きい場合でも、Intelのドキュメントは非常に優れており、正確です。
test
は非破壊的なand
であり、操作の結果を返しませんが、フラグレジスタを適宜設定します。それが本当にテストするものを知るには、以下の指示を確認する必要があります。多くの場合、jz
条件付きジャンプと組み合わせて、レジスタを0に対してチェックするためにoutが使用されます。