web-dev-qa-db-ja.com

テストのポイント%eax%eax

可能性のある複製:
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自体がよく、どのような状況でジャンプしないのか?

私は一般的にプログラミングの初心者なので、誰かがこれを説明してくれたらとても感謝しています。ありがとう!

112
pauliwago

CMPはオペランドを減算し、フラグを設定します。つまり、差がゼロ(オペランドが等しい)の場合、ゼロフラグを設定します。

TESTは、AND演算の結果がゼロの場合、ゼロ変数ZFを設定します。 2つのオペランドが等しい場合、両方がゼロの場合、ビット単位のANDはゼロになります。 TESTは、結果で最上位ビットが設定されている場合は符号フラグSFを設定し、設定ビット数が偶数の場合はパリティフラグPFも設定します。

JE [Jump if Equals]は、ゼロフラグをテストし、フラグが設定されている場合にジャンプします。 JEJZ [ゼロの場合ジャンプ]のエイリアスなので、逆アセンブラーはオペコードに基づいて1つを選択できません。 JEは、CMPの引数が等しい場合にゼロフラグが設定されるため、そのような名前が付けられます。

そう、

TEST %eax, %eax
JE   400e77 <phase_1+0x23>

%eaxがゼロの場合ジャンプします。

129
John Dvorak

一部の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
}
45

これは、EAXがゼロかどうかを確認します。命令testは、引数間でビットごとにANDを実行し、EAXにゼロが含まれる場合、結果はZFまたはZeroFlagを設定します。

11
ppeterka

testが2つのオペランドを「and」しているのは正しいです。しかし、結果は破棄され、残っているのは重要な部分だけであり、フラグのみです。これらは設定されており、それがtest命令が使用される(そして存在する)理由です。

JEは、等しくない場合(前の命令が比較であった場合に意味を持ちます)、実際に何をするかではなく、ZFフラグが設定されている場合にジャンプします。また、testによって設定されるフラグの1つであるため、この命令シーケンス(テストx、x; je ...)には、xが0のときにジャンプするという意味があります。

このような質問(および詳細)については、x86命令に関する本をお勧めします。本当に大きい場合でも、Intelのドキュメントは非常に優れており、正確です。

3
flolo

testは非破壊的なandであり、操作の結果を返しませんが、フラグレジスタを適宜設定します。それが本当にテストするものを知るには、以下の指示を確認する必要があります。多くの場合、jz条件付きジャンプと組み合わせて、レジスタを0に対してチェックするためにoutが使用されます。

3