装配 - CMP后的JG / JNLE / JL / JNGE
116151 观看
4回复
我不理解JG/JNLE/JL/JNGE
CMP之后的说明。
例如,如果我有:
CMP al,dl
jg label1
当al=101; dl =200
。
我们问jg
什么?是al>dl
吗?还是al-dl>0
?
在下一个代码上相同的prolbem:
test al,dl
jg label1
我不明白我们比较什么,以及我们问什么“ jg
”。
换句话说,我不明白我们何时会跳转到label1,何时不会。
作者: Adam Sh 的来源 发布者: 2019 年 7 月 9 日回应 (4)
107像
执行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
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)
使用时需要小心,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 |
+--------+------------------------------+-------------+--------------------+
然后是未签名的:
+--------+------------------------------+-------------+--------------------+
|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 | | |
+--------+------------------------------+-------------+--------------------+
作者: paxdiablo
发布者: 08.03.2012 12:55
4像
Wikibooks对跳转指令有一个相当不错的总结。基本上,实际上有两个阶段:
cmp_instruction op1, op2
根据结果设置各种标志,和
jmp_conditional_instruction address
它将根据这些标志的结果执行跳转。
Compare(cmp
)将基本上计算减法op1-op2
,但是,这不存储; 而是仅设置标志结果。所以如果你这样做也是cmp eax, ebx
如此eax-ebx
- 然后根据是否为正,负或零决定设置标志。
这里有更详细的参考。
作者: user257111 发布者: 08.03.2012 12:551像
对于有符号和无符号数,二进制补码的加法和减法是相同的
关键的观察是CMP基本上是减法,并且:
在二进制补码(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
。在英特尔语法中,这将是cmp al, bl
在此之后,将进行以下跳转:
- JB,因为0 <255
- JNA,因为!(0> 255)
- JNL,因为!(0 <-1)
- JG,因为0> -1
注意在这个特定的例子中签名是如何重要的,例如JB被采用但不是JL。
JLE / JNG等等/否定版本只是别名
通过查看英特尔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).
作者: Ciro Santilli 新疆改造中心996ICU六四事件
发布者: 15.06.2019 08:26
0像
命令JG只是意味着:如果更大则跳转。前面指令的结果存储在某些处理器标志中(在此它将测试ZF = 0和SF = OF)并且跳转指令根据它们的状态动作。
作者: Lukasz 发布者: 08.03.2012 01:02来自类别的问题 :
- assembly x86中“非暂时”内存访问的含义是什么?
- assembly 你如何在gcc中从C / C ++源获得汇编程序输出?
- assembly 什么是好的C反编译器?
- assembly 在主要C / C ++编译器生成的代码中注册分配规则
- assembly 解释汇编代码
- assembly 编写固件:汇编还是高级?
- x86 将3D数学转换为SSE或其他SIMD需要多少加速?
- x86 System.BadImageFormatException:无法加载文件或程序集(来自installutil.exe)
- x86 EBP帧指针寄存器的用途是什么?
- x86 直接读程序计数器
- x86 有什么好的x86汇编语言资源?
- eflags 装配 - CMP后的JG / JNLE / JL / JNGE
- eflags x86上的子指令和受影响的标志
- eflags 如何在x86程序集中设置或清除溢出标志?
- eflags cmp指令何时修改zf标志?[x86 MASM]
- eflags x86组件-CMP无法正确设置零标志
- eflags Windows 64位调用约定