assembly 组装-CMP后的JG/JNLE/JL/JNGE

bwitn5fc  于 2023-02-19  发布在  其他
关注(0)|答案(4)|浏览(157)

我不理解JG/JNLE/JL/JNGE指令,它在CMP之后。
例如,如果我有:

CMP al,dl
jg label1

al=101; dl =200 .
我们问jg什么?它是在al>dl上?还是在al-dl>0上?
下一个代码也有同样的问题:

test al,dl
jg label1

我不明白我们在比较什么,以及我们在问什么“jg“。
换句话说,我不明白我们什么时候会跳到标签1,什么时候不会。

xuo3flqw

xuo3flqw1#

When you do a cmp a,b , the flags are set as if you had calculated a - b . Then the conditional jump instructions check those flags to see if the jump should be made.
In other words, the first block of code you have (with my comments added):

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

would jump to label1 if and only if al was greater than dl .
You're probably better off thinking of it as al > dl but the two choices you have there are mathematically equivalent:

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

You need to be careful when using jg inasmuch as it assumes your values were signed. So, if you compare the bytes 101 ( 101 in two's complement) with 200 ( -56 in two's complement), the former will actually be greater. If that's not what was desired, you should use the equivalent unsigned comparison.
See here for more detail on jump selection, reproduced below for completeness, in the order of:

  • ones that aren't signed or unsigned compares when used after CMP.
  • unsigned ones.
  • signed ones.
InstructionDescriptionSigned-nessConditions checked
JOJump if overflowOF = 1
JNOJump if not overflowOF = 0
JSJump if signSF = 1
JNSJump if not signSF = 0
JEJZJump if equalJump if zeroZF = 1
JNEJNZJump if not equalJump if not zeroZF = 0
JPJPEJump if parityJump if parity evenPF = 1
JNPJPOJump if no parityJump if parity oddPF = 0
JCXZJECXZJRCXZJump if CX is zeroJump if ECX is zeroJump if RCX is zeroCX = 0ECX = 0RCX = 0
JBJNAEJCJump if belowJump if not above or equalJump if carryunsignedCF = 1
JNBJAEJNCJump if not belowJump if above or equalJump if not carryunsignedCF = 0
JBEJNAJump if below or equalJump if not aboveunsignedCF = 1 or ZF = 1
JAJNBEJump if aboveJump if not below or equalunsignedCF = 0 and ZF = 0
JLJNGEJump if lessJump if not greater or equalsignedSF <> OF
JGEJNLJump if greater or equalJump if not lesssignedSF = OF
JLEJNGJump if less or equalJump if not greatersignedZF = 1 or SF <> OF
JGJNLEJump if greaterJump if not less or equalsignedZF = 0 and SF = OF
ovfsdjhp

ovfsdjhp2#

Wikibooks对jump instructions有一个很好的总结,基本上,它实际上有两个阶段:

cmp_instruction op1, op2

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

jmp_conditional_instruction address

其将基于那些标志的结果执行跳转。
Compare(cmp)将基本上计算减法op1-op2,然而,这不被存储;而是只设置标志结果,所以如果你做了cmp eax, ebx,就等于说eax-ebx--然后根据它是正的,负的还是零来决定设置哪些标志。
更详细的参考here

cnwbcb6i

cnwbcb6i3#

    • 二进制补码中的加法和减法对于有符号数和无符号数是相同的**

关键的观察结果是CMP基本上是减法,并且:
two's complement(x86使用的整数表示)中,有符号加法和无符号加法是完全相同的运算
这允许例如硬件开发者仅用一个电路更有效地实现它。
因此,例如,当您将输入字节提供给x86 ADD指令时,它并不关心这些字节是否有符号。
但是,ADD会根据操作期间发生的情况设置一些标志:

  • 进位:无符号加法或减法结果不适合位大小,例如:0xFF +0x01或0x00 - 0x01

对于加法,我们需要将1进位到下一级。

  • sign:结果设置了最高位,即:如果解释为有符号,则为负。
  • 溢出:输入的最高位都是0和0或1和1,而反相的输出则相反。

即,带符号操作以不可能的方式更改了符号(例如,正+正或负
然后,我们可以解释这些标志,使比较符合我们对有符号或无符号数字的期望。
这种解读正是JA vs JG和JB vs 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。
Runnable example with assertions.

    • 等于/否定版本(如JLE/JNG)只是别名**

通过查看Intel 64 and IA-32 Architectures Software Developer's Manuals Volume 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).
fwzugrvs

fwzugrvs4#

命令JG的意思是:大于则跳转.前面指令的结果存储在某些处理器标志中(在此,它将测试ZF是否=0且SF是否=OF),并且跳转指令根据它们的状态执行操作。

相关问题