装配 - CMP后的JG/JNLE/JL/JNGE

Ada*_* Sh 53 x86 assembly eflags

我不理解JG/JNLE/JL/JNGECMP之后的说明.

例如,如果我有:

CMP al,dl
jg label1
Run Code Online (Sandbox Code Playgroud)

al=101; dl =200.

我们问jg什么?是al>dl吗?还是al-dl>0

在下一个代码上相同的prolbem:

test al,dl
jg label1
Run Code Online (Sandbox Code Playgroud)

我不明白我们比较什么,以及我们问什么" jg".

换句话说,我不明白我们何时会跳转到label1,何时不会.

谢谢.

pax*_*blo 112

执行a时cmp a,b,标记设置就像您计算的一样a - b.

然后jmp-type指令检查那些标志以查看是否应该进行跳转.

换句话说,您拥有的第一个代码块(添加了我的注释):

cmp al,dl     ; set flags based on the comparison
jg label1     ; then jump based on the flags
Run Code Online (Sandbox Code Playgroud)

label1如果且仅al在大于的情况下会跳转到dl.

你最好不要考虑它,al > dl但你在那里的两个选择在数学上是等价的:

al > dl
al - dl > dl - dl (subtract dl from both sides)
al - dl > 0       (cancel the terms on the right hand side)
Run Code Online (Sandbox Code Playgroud)

使用时需要小心,jg因为它假定您的值已签名.因此,如果将字节 101(二进制补码中的101)与200(二进制中的-56)进行比较,前者实际上会更大.如果这不是您想要的,那么您应该使用等效的无符号比较.

有关跳转选择的更多详细信息,请参见此处,下面重现完整性.首先是签名不合适的:

+--------+------------------------------+-------------+--------------------+
|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            |
+--------+------------------------------+-------------+--------------------+
Run Code Online (Sandbox Code Playgroud)

然后是未签名的:

+--------+------------------------------+-------------+--------------------+
|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   |             |                    |
+--------+------------------------------+-------------+--------------------+
Run Code Online (Sandbox Code Playgroud)

最后,签名的:

+--------+------------------------------+-------------+--------------------+
|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    |             |                    |
+--------+------------------------------+-------------+--------------------+
Run Code Online (Sandbox Code Playgroud)

  • @Adam,因为`jg`适用于_signed_值(八位二进制补码中的200实际上是-56)。如果您想将它们作为无符号值处理,请使用“ja”。我会更新答案。 (2认同)
  • 值得注意的是,在gdb的语法(GAS)中,cmp(cmpl)的操作数顺序是反转的,您可以在https://en.wikibooks.org/wiki/X86_Assembly/Control_Flow上看到,它列出了Intel和GAS变体. (2认同)

小智 5

维基教科书对跳转指令有相当好的总结。基本上,实际上有两个阶段:

cmp_instruction op1, op2
Run Code Online (Sandbox Code Playgroud)

它根据结果设置各种标志,以及

jmp_conditional_instruction address
Run Code Online (Sandbox Code Playgroud)

它将根据这些标志的结果执行跳转。

Compare( cmp) 基本上会计算减法op1-op2,但是,这不会被存储;相反,仅设置标志结果。因此,如果您cmp eax, ebx这样做,那就等于说eax-ebx- 然后根据是正数、负数还是零来决定要设置哪些标志。

更详细的参考这里