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.
Instruction
Description
Signed-ness
Conditions checked
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
JEJZ
Jump if equalJump if zero
ZF = 1
JNEJNZ
Jump if not equalJump if not zero
ZF = 0
JPJPE
Jump if parityJump if parity even
PF = 1
JNPJPO
Jump if no parityJump if parity odd
PF = 0
JCXZJECXZJRCXZ
Jump if CX is zeroJump if ECX is zeroJump if RCX is zero
CX = 0ECX = 0RCX = 0
JBJNAEJC
Jump if belowJump if not above or equalJump if carry
unsigned
CF = 1
JNBJAEJNC
Jump if not belowJump if above or equalJump if not carry
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).
4条答案
按热度按时间xuo3flqw1#
When you do a
cmp a,b
, the flags are set as if you had calculateda - 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):
would jump to
label1
if and only ifal
was greater thandl
.You're probably better off thinking of it as
al > dl
but the two choices you have there are mathematically equivalent:You need to be careful when using
jg
inasmuch as it assumes your values were signed. So, if you compare the bytes101
(101
in two's complement) with200
(-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:
ovfsdjhp2#
Wikibooks对jump instructions有一个很好的总结,基本上,它实际上有两个阶段:
它根据结果设置各种标志,
其将基于那些标志的结果执行跳转。
Compare(
cmp
)将基本上计算减法op1-op2
,然而,这不被存储;而是只设置标志结果,所以如果你做了cmp eax, ebx
,就等于说eax-ebx
--然后根据它是正的,负的还是零来决定设置哪些标志。更详细的参考here。
cnwbcb6i3#
关键的观察结果是CMP基本上是减法,并且:
在two's complement(x86使用的整数表示)中,有符号加法和无符号加法是完全相同的运算
这允许例如硬件开发者仅用一个电路更有效地实现它。
因此,例如,当您将输入字节提供给x86 ADD指令时,它并不关心这些字节是否有符号。
但是,ADD会根据操作期间发生的情况设置一些标志:
对于加法,我们需要将1进位到下一级。
即,带符号操作以不可能的方式更改了符号(例如,正+正或负
然后,我们可以解释这些标志,使比较符合我们对有符号或无符号数字的期望。
这种解读正是JA vs JG和JB vs JL为我们所做的!
下面是GNU GAS的一段代码片段,使之更加具体:
请注意,AT & T语法是"反向"的:
mov src, dst
。因此,您必须在头脑中将条件代码的操作数反向,才能理解cmp
。在Intel语法中,这将是cmp al, bl
在这一点之后,将进行以下跳跃:
注意在这个特殊的例子中符号是如何起作用的,例如JB被取而不是JL。
Runnable example with assertions.
通过查看Intel 64 and IA-32 Architectures Software Developer's Manuals Volume 2部分"Jcc-满足条件时跳转",我们看到编码是相同的,例如:
fwzugrvs4#
命令JG的意思是:大于则跳转.前面指令的结果存储在某些处理器标志中(在此,它将测试ZF是否=0且SF是否=OF),并且跳转指令根据它们的状态执行操作。