123

私はいくつかのアセンブリを理解しようとしています。

次のようなアセンブリ、私はtestlラインに興味があります:

000319df  8b4508        movl   0x08(%ebp), %eax  
000319e2  8b4004        movl   0x04(%eax), %eax  
000319e5  85c0          testl  %eax, %eax  
000319e7  7407          je     0x000319f0  

私はとのtestl間のそのポイントを理解しよう%eaxとしてい%eaxますか?このコードの詳細は重要ではないと思います。私はテスト自体を理解しようとしているだけです。値は常に真であるとは限りません。

4

8 に答える 8

95

eaxが 0 か、それより上か、または下かをテストします。この場合、eaxが 0 の場合にジャンプが実行されます。

于 2008-09-29T01:23:43.687 に答える
95

の意味はtest、引数を一緒に AND し、結果がゼロかどうかをチェックすることです。したがって、このコードは EAX がゼロかどうかをテストします。jeゼロの場合はジャンプします。

cmp eax, 0ところで、これはコンパイラが一般的にこのようにする理由であるよりも小さな命令を生成します。

于 2008-09-29T01:24:49.877 に答える
35

テスト命令は、オペランド間の論理 AND 演算を実行しますが、結果をレジスタに書き戻すことはしません。フラグのみが更新されます。

テスト eax の例では、eax がゼロの場合は eax がゼロ フラグを設定し、最上位ビットが設定されている場合は符号フラグを設定し、その他のフラグも設定します。

Jump if Equal (je) 命令は、ゼロ フラグが設定されている場合にジャンプします。

次のように、コードをより読みやすいコードに変換できます。

cmp eax, 0
je  somewhere

機能は同じですが、数バイト多くのコードスペースが必要です。これが、コンパイラが比較ではなくテストを発行した理由です。

于 2008-09-29T01:29:03.297 に答える
26

testに似andていますが、FLAGS のみを書き込み、両方の入力を変更しない点が異なります。2 つの異なる入力を使用すると、一部のビットがすべてゼロかどうか、または少なくとも 1 つが設定されているかどうかをテストするのに役立ちます。(たとえばtest al, 3、EAX が 4 の倍数の場合 (したがって、下位 2 ビットが両方ともゼロになっている場合)、ZF を設定します)。


test eax,eaxすべてのフラグをまったく同じ方法で設定しcmp eax, 0ます

廃止された AF (ASCII/BCD 命令で使用される補助キャリー フラグ) を除きます。 TEST は undefinedのままにしますが、CMP は「結果に従って」設定します。ゼロを減算しても 4 番目から 5 番目のビットへのキャリーを生成できないため、CMP は常に AF をクリアする必要があります。


TEST はより小さく (即時ではなく)、時には高速です (CMP よりも多くの場合、より多くの CPU で比較分岐 uop にマクロ融合できます)。 これによりtest、レジスタをゼロと比較するための推奨イディオムが作成されます。cmp reg,0これは、セマンティックな意味に関係なく使用できるのぞき穴の最適化です。

即値 0 で CMP を使用する唯一の一般的な理由は、メモリ オペランドと比較する場合です。たとえばcmpb $0, (%esi)、暗黙的な長さの C スタイルの文字列の末尾にゼロ バイトがあるかどうかを確認するには、次のようにします。


AVX512F はkortestw k1, k2ktestb/w/d/q k1, k2、 AVX512 マスク レジスタ (k0..k7) で動作するAVX512DQ/BW (KNL ではなく Skylake-X) add を追加しますtestが、整数ORまたはAND命令と同じ方法で通常の FLAGS を設定します。(SSE4ptestや SSEのようなものucomiss: SIMD ドメインの入力であり、整数の FLAGS になります。)

kortestw k1,k1SSE/AVX2 (v)pmovmskb/ps/pd+testまたはcmp.


jzvsの使用はje混乱を招く可能性があります。

jzjeは、文字通り同じ命令、つまりマシンコードの同じオペコードです。 それらは同じことを行いますが、人間にとって異なる意味を持ちます。逆アセンブラー (および通常はコンパイラーからの asm 出力) は 1 つしか使用しないため、セマンティックの区別は失われます。

cmpsub2 つの入力が等しい場合 (つまり、減算結果が 0 の場合)、ZF を設定します。je(等しい場合はジャンプ) は、意味的に関連する同義語です。

test %eax,%eax/and %eax,%eaxは、結果がゼロの場合に再び ZF を設定しますが、「等しい」テストはありません。テスト後の ZF は、2 つのオペランドが等しいかどうかを示しません。したがってjz、(jump if zero) は意味的に関連する同義語です。

于 2016-06-25T20:45:19.103 に答える
5

このコードスニペットは、何か、おそらく構造体またはオブジェクトへのポインターが与えられたサブルーチンからのものです。2行目は、そのポインターを逆参照し、そのポインターから値をフェッチします。おそらく、それ自体がポインターであるか、2番目のメンバー(オフセット+4)として格納されている単なるintです。3行目と4行目は、この値がゼロであるかどうかをテストし(ポインターの場合はNULL)、ゼロの場合は次のいくつかの操作(図には示されていません)をスキップします。

ゼロのテストは、即時の文字通りのゼロ値との比較としてコーディングされることがありますが、これを書いたコンパイラ(または人間?)は、パイプラインやレジスタなどの最新のCPUを考慮して、テスト操作がより高速に実行されると考えていた可能性があります名前の変更。これは、明白ではあるがおそらく遅いMOV EAX、#0(古い表記を使用)ではなく、XOR EAX、EAX(コロラドの誰かのナンバープレートで見た!)でレジスターをクリアするという考えを持っている同じトリックのバッグからのものです)。

asmでは、perlのように、TMTOWTDI。

于 2008-09-29T03:40:00.550 に答える
3

eax がゼロの場合、条件付きジャンプが実行されます。それ以外の場合は、319e9 で実行が続行されます。

于 2008-09-29T01:25:07.787 に答える
0

一部のプログラムでは、バッファ オーバーフローのチェックに使用できます。割り当てられたスペースの一番上に 0 が配置されます。スタックにデータを入力した後、割り当てられたスペースがオーバーフローしていないことを確認するために、割り当てられたスペースの最初にある 0 を探します。

エクスプロイト演習の stack0 演習で、オーバーフローしているかどうかを確認するために使用されました。オーバーフローがなく、そこにゼロがある場合は、「再試行」と表示されます。

0x080483f4 <main+0>:    push   ebp
0x080483f5 <main+1>:    mov    ebp,esp
0x080483f7 <main+3>:    and    esp,0xfffffff0
0x080483fa <main+6>:    sub    esp,0x60                     
0x080483fd <main+9>:    mov    DWORD PTR [esp+0x5c],0x0 ;puts a zero on stack
0x08048405 <main+17>:   lea    eax,[esp+0x1c]
0x08048409 <main+21>:   mov    DWORD PTR [esp],eax
0x0804840c <main+24>:   call   0x804830c <gets@plt>
0x08048411 <main+29>:   mov    eax,DWORD PTR [esp+0x5c] 
0x08048415 <main+33>:   test   eax,eax                  ; checks if its zero
0x08048417 <main+35>:   je     0x8048427 <main+51>
0x08048419 <main+37>:   mov    DWORD PTR [esp],0x8048500 
0x08048420 <main+44>:   call   0x804832c <puts@plt>
0x08048425 <main+49>:   jmp    0x8048433 <main+63>
0x08048427 <main+51>:   mov    DWORD PTR [esp],0x8048529
0x0804842e <main+58>:   call   0x804832c <puts@plt>
0x08048433 <main+63>:   leave
0x08048434 <main+64>:   ret
于 2016-12-06T21:19:36.093 に答える
-4

jg ,<strong>jleを簡単に見つけることができれば、 jleが適していることがわかります。%edx がゼロの場合、ZF=1、しかし %edx がゼロではなく -1 の場合、テスト後、OF=0、そしてSF =1なので、ジャンプを実装するフラグ=trueです。申し訳ありませんが、私の英語は下手ですtestl %edx,%edx. jle .L3(SF^OF)|ZF

于 2017-03-14T07:35:26.293 に答える