web-dev-qa-db-ja.com

アセンブリ-CMP後のJG / JNLE / JL / JNGE

CMPの後に来るJG/JNLE/JL/JNGE命令がわかりません。

たとえば、私が持っている場合:

CMP al,dl
jg label1

al=101; dl =200の場合。

jgに尋ねる内容は? al>dlにありますか?またはal-dl>0

次のコードでも同じ問題:

test al,dl
jg label1

私たちが何を比較するのか、そして「jg」を尋ねるのはわかりません。

つまり、いつlabel1にジャンプするか、いつしないかがわかりません。

51
Adam Sh

cmp a,bを実行すると、a - bを計算したかのようにフラグが設定されます。

次に、jmp- type命令がこれらのフラグをチェックして、ジャンプを行う必要があるかどうかを確認します。

言い換えれば、あなたが持っているコードの最初のブロック(私のコメントが追加されています):

cmp al,dl     ; set flags based on the comparison
jg label1     ; then jump based on the flags

aldlより大きい場合にのみ、label1にジャンプします。

おそらくal > dlと考える方が良いでしょうが、そこにある2つの選択肢は数学的に同等です:

al > dl
al - dl > dl - dl (subtract dl from both sides)
al - dl > 0       (cancel the terms on the right hand side)

jgを使用する場合は、値が署名されていると想定するため、注意する必要があります。したがって、bytes101(2の補数の101)と200(2の補数の-56)を比較すると、前者は実際に大きくなります。それが望まれていない場合は、同等の符号なし比較を使用する必要があります。

ジャンプの選択の詳細については here を参照してください。完全性のために以下に再現します。まず、符号付きが適切でないもの:

+--------+------------------------------+-------------+--------------------+
|Instr   | Description                  | signed-ness | Flags              |
+--------+------------------------------+-------------+--------------------+
| JO     | Jump if overflow             |             | OF = 1             |
+--------+------------------------------+-------------+--------------------+
| JNO    | Jump if not overflow         |             | OF = 0             |
+--------+------------------------------+-------------+--------------------+
| JS     | Jump if sign                 |             | SF = 1             |
+--------+------------------------------+-------------+--------------------+
| JNS    | Jump if not sign             |             | SF = 0             |
+--------+------------------------------+-------------+--------------------+
| JE/    | Jump if equal                |             | ZF = 1             |
| JZ     | Jump if zero                 |             |                    |
+--------+------------------------------+-------------+--------------------+
| JNE/   | Jump if not equal            |             | ZF = 0             |
| JNZ    | Jump if not zero             |             |                    |
+--------+------------------------------+-------------+--------------------+
| JP/    | Jump if parity               |             | PF = 1             |
| JPE    | Jump if parity even          |             |                    |
+--------+------------------------------+-------------+--------------------+
| JNP/   | Jump if no parity            |             | PF = 0             |
| JPO    | Jump if parity odd           |             |                    |
+--------+------------------------------+-------------+--------------------+
| JCXZ/  | Jump if CX is zero           |             | CX = 0             |
| JECXZ  | Jump if ECX is zero          |             | ECX = 0            |
+--------+------------------------------+-------------+--------------------+

次に、署名されていないもの:

+--------+------------------------------+-------------+--------------------+
|Instr   | Description                  | signed-ness | Flags              |
+--------+------------------------------+-------------+--------------------+
| JB/    | Jump if below                | unsigned    | CF = 1             |
| JNAE/  | Jump if not above or equal   |             |                    |
| JC     | Jump if carry                |             |                    |
+--------+------------------------------+-------------+--------------------+
| JNB/   | Jump if not below            | unsigned    | CF = 0             |
| JAE/   | Jump if above or equal       |             |                    |
| JNC    | Jump if not carry            |             |                    |
+--------+------------------------------+-------------+--------------------+
| JBE/   | Jump if below or equal       | unsigned    | CF = 1 or ZF = 1   |
| JNA    | Jump if not above            |             |                    |
+--------+------------------------------+-------------+--------------------+
| JA/    | Jump if above                | unsigned    | CF = 0 and ZF = 0  |
| JNBE   | Jump if not below or equal   |             |                    |
+--------+------------------------------+-------------+--------------------+

そして最後に、署名されたもの:

+--------+------------------------------+-------------+--------------------+
|Instr   | Description                  | signed-ness | Flags              |
+--------+------------------------------+-------------+--------------------+
| JL/    | Jump if less                 | signed      | SF <> OF           |
| JNGE   | Jump if not greater or equal |             |                    |
+--------+------------------------------+-------------+--------------------+
| JGE/   | Jump if greater or equal     | signed      | SF = OF            |
| JNL    | Jump if not less             |             |                    |
+--------+------------------------------+-------------+--------------------+
| JLE/   | Jump if less or equal        | signed      | ZF = 1 or SF <> OF |
| JNG    | Jump if not greater          |             |                    |
+--------+------------------------------+-------------+--------------------+
| JG/    | Jump if greater              | signed      | ZF = 0 and SF = OF |
| JNLE   | Jump if not less or equal    |             |                    |
+--------+------------------------------+-------------+--------------------+
107
paxdiablo

ウィキブックスには jump instructions のかなり良い要約があります。基本的に、実際には2つの段階があります。

cmp_instruction op1, op2

結果に基づいてさまざまなフラグを設定します。

jmp_conditional_instruction address

これらのフラグの結果に基づいてジャンプを実行します。

比較(cmp)は基本的に減算op1-op2を計算しますが、これは保存されません。代わりに、フラグの結果のみが設定されます。したがって、cmp eax, ebxを実行した場合、eax-ebxを指定したのと同じです。次に、設定するフラグが正か負かゼロに基づいて決定します。

より詳細なリファレンス こちら

4
user257111

2の補数の加算と減算は、符号付き数値と符号なし数値で同じです

重要な点は、CMPは基本的に減算であるということです。

2の補数 (x86で使用される整数表現)では、符号付き加算と符号なし加算はまったく同じ演算です

これにより、たとえばハードウェア開発者は1つの回路だけでより効率的に実装できます。

したがって、たとえばx86 ADD命令に入力バイトを与えた場合、それらが署名されているかどうかは関係ありません。

ただし、ADDは操作中に何が起こったかに応じていくつかのフラグを設定します。

  • キャリー:符号なしの加算または減算の結果がビットサイズに適合しない、例:0xFF + 0x01または0x00-0x01

    さらに、1を次のレベルに運ぶ必要があります。

  • 符号:結果に最上位ビットが設定されています。つまり、署名済みと解釈された場合は負です。

  • オーバーフロー:入力の最上位ビットは0と0または1と1の両方であり、出力は反転します。

    つまり署名された操作は不可能な方法でシジネスを変更しました(例:ポジティブ+ポジティブまたはネガティブ

次に、これらのフラグを、符号付きまたは符号なしの数値に対する期待に一致するように解釈できます。

この解釈はまさに、JA対JGおよびJB対JLが行うことです!

コード例

GNU GASは、これをより具体的にするためのコードスニペットです。

/* 0x0 ==
 *
 * * 0 in 2's complement signed
 * * 0 in 2's complement unsigned
 */
mov $0, %al

/* 0xFF ==
 *
 * *  -1 in 2's complement signed
 * * 255 in 2's complement unsigned
 */
mov $0xFF, %bl

/* Do the operation "Is al < bl?" */
cmp %bl, %al

AT&T構文は「後方」であることに注意してください:mov src, dst。そのため、cmpで意味を成すためには、条件コードのオペランドを精神的に逆にする必要があります。 Intel構文では、これはcmp al, bl

このポイントの後、次のジャンプが行われます。

  • JB、0 <255であるため
  • JNA、!(0> 255)
  • JNL、!(0 <-1)
  • JG、0> -1であるため

この特定の例で、署名の重要性に注意してください。 JBは取得されますが、JLは取得されません。

アサーション付きの実行可能な例

等しい/ JLE/JNGのような否定バージョンは単なるエイリアスです

Intel 64およびIA-32アーキテクチャソフトウェア開発者マニュアル第2巻 セクション「Jcc-条件が満たされた場合ジャンプ」を見ると、エンコードが同一であることがわかります。たとえば、

Opcode  Instruction  Description
7E cb   JLE rel8     Jump short if less or equal (ZF=1 or SF ≠ OF).
7E cb   JNG rel8     Jump short if not greater (ZF=1 or SF ≠ OF).

コマンドJGは、単に大きい場合はジャンプを意味します。前の命令の結果は、特定のプロセッサフ​​ラグに保存され(この場合、ZF = 0およびSF = OFかどうかをテストします)、ジャンプ命令はそれらの状態に従って動作します。

0
Lukasz