x86 条件分支指令说明
EFLAGS
x86 处理器的 EFLAGS 寄存器有很多位,但是与条件分支相关的是其中的 5 位:
ZF
bit6,零标志位。执行指令之后,其结果为 0 时,该标志位置 1,不为 0 时置 0。SF
bit7,符号标志位。执行指令之后,其结果为负数时,该标志位置 1,否则置 0。CF
bit0,进位标志位。执行指令之后,发生向超出最高位进位,或者从超出最高位借位时,该标志位置 1,否则置 0。OF
bit11,溢出标志位。执行指令之后,超出机器能表示的范围时,该标志位置 1,否则置 0。PF
bit2,奇偶标志位。执行指令之后,结果中的所有位中,1 的个数位偶数时,该标志位置 1,否则置 0。
CLC
指令: 该指令将 CF 清 0STC
指令: 该指令将 CF 置 1CMC
指令: 该指令将 CF 取反
条件跳转指令列表
- 对于使用无符号数的比较,则使用 above (A)和 below (B)关键字比较;
- 对于使用有符号数的比较,则使用 greater (G)和 less (L)关键字进行比较。
序 号 | 指 令 | 描 述 | EFLAGS |
1 | JO | 如果溢出(overflow),则跳转 | OF == 1 |
2 | JNO | 如果没溢出(not overflow),则跳转 | OF == 0 |
3 | JB | 如果小于(below),则跳转 | CF == 1 |
4 | JC | 如果 CF == 1,则跳转 | CF == 1 |
5 | JNAE | 如果不大于(not above)或者等于 | CF == 1 |
6 | JNB | 如果不小于(not below) | CF == 0 |
7 | JNC | 如果 CF != 1,则跳转 | CF == 0 |
8 | JAE | 如果大于(above)或等于,则跳转 | CF == 0 |
9 | JZ | 如果 ZF == 1,则跳转 | ZF == 1 |
10 | JE | 如果相等(equal),则跳转 | ZF == 1 |
11 | JNZ | 如果 ZF != 1,则跳转 | ZF == 0 |
12 | JNE | 如果不相等(not equal),则跳转 | ZF == 0 |
13 | JBE | 如果小于(below)或等于,则跳转 | CF == 1 && ZF == 1 |
14 | JNA | 如果不大于(not above),则跳转 | CF == 1 && ZF == 1 |
15 | JNBE | 如果不小于(not below)或等于,则跳转 | CF == 0 && ZF == 0 |
16 | JA | 如果大于(above),则跳转 | CF == 0 && ZF == 0 |
17 | JS | 如果 SF == 1,则跳转 | SF == 1 |
18 | JNS | 如果 SF == 0,则跳转 | SF == 0 |
19 | JP | 如果奇偶检验(parity),则跳转 | PF == 1 |
20 | JPE | 如果偶检验(parity even),则跳转 | PF == 1 |
21 | JNP | 如果不奇偶检验(not parity),则跳转 | PF == 0 |
22 | JPO | 如果奇检验(parity odd),则跳转 | PF == 0 |
23 | JL | 如果小于(less)则跳转 | SF != OF |
24 | JNGE | 如果不大于(not greater)或等于则跳转 | SF != OF |
25 | JNL | 如果不小于(not less)则跳转 | SF == OF |
26 | JGE | 如果大于(greater)或等于,则跳转 | SF == OF |
27 | JLE | 如果小于(less)或等于,则跳转 | ZF == 1 || SF != OF |
28 | JNG | 如果不大于(greater),则跳转 | ZF == 1 || SF != OF |
29 | JNLE | 如果不小于(not less)或等于,则跳转 | ZF == 0 && SF == OF |
30 | JG | 如果大于(greater),则跳转 | ZF == 0 && SF == OF |
31 | JCXZ JECXZ JRCXZ |
当 CX/ECX/RCX 寄存器为 0 时跳转 | 三条指令是一样的, 只跳转8位偏移量 |
循环指令
下面指令会将 CX/ECX/RCX 自动减去 1,如果 CX/ECX/RCX 不为 0 则跳转到指定的 8 位偏移标签。
序 号 | 指 令 | 描 述 | 其 他 |
1 | LOOP | CX/ECX/RCX != 0,则跳转 | 只有8位偏移 |
1 | LOOPE / LOOPZ | CX/ECX/RCX != 0,并且 ZF == 1,则跳转 | 只有8位偏移 |
1 | LOOPNE / LOOPNZ | CX/ECX/RCX != 0,并且 ZF == 0,则跳转 | 只有8位偏移 |
loop 指令有个灾难:如果将 CX/ECX/RCX 设置为 0,执行 loop 时会自动减去 1,就会变成 -1 回环,会陷入很长很长的循环。这时可以配合 JCXZ 指令判断 CX/ECX/RCX 为 0 则跳转来避免。
条件数据传送指令
也可以利用标志位来达到按条件数据传送的功能指令。条件数据传送指令置限于寄存器与寄存器、或者寄存器与存储器之间的数据传送,不支持立即数传送。
- 对于使用无符号数的比较,则使用 above (A)和 below (B)关键字比较;
- 对于使用有符号数的比较,则使用 greater (G)和 less (L)关键字进行比较。
序 号 | 指 令 | 描 述 | EFLAGS |
1 | CMOVO | 如果溢出(overflow),则传送 | OF == 1 |
2 | CMOVNO | 如果没溢出(not overflow),则传送 | OF == 0 |
3 | CMOVB | 如果小于(below),则传送 | CF == 1 |
4 | CMOVC | 如果 CF == 1,则传送 | CF == 1 |
5 | CMOVNAE | 如果不大于(not above)或者等于,则传送 | CF == 1 |
6 | CMOVNB | 如果不小于(not below),则传送 | CF == 0 |
7 | CMOVNC | 如果 CF != 1,则传送 | CF == 0 |
8 | CMOVAE | 如果大于(above)或等于,则传送 | CF == 0 |
9 | CMOVZ | 如果 ZF == 1,则传送 | ZF == 1 |
10 | CMOVE | 如果相等(equal),则传送 | ZF == 1 |
11 | CMOVNZ | 如果 ZF != 1,则传送 | ZF == 0 |
12 | CMOVNE | 如果不相等(not equal),则传送 | ZF == 0 |
13 | CMOVBE | 如果小于(below)或等于,则传送 | CF == 1 && ZF == 1 |
14 | CMOVNA | 如果不大于(not above),则传送 | CF == 1 && ZF == 1 |
15 | CMOVNBE | 如果不小于(not below)或等于,则传送 | CF == 0 && ZF == 0 |
16 | CMOVA | 如果大于(above),则传送 | CF == 0 && ZF == 0 |
17 | CMOVS | 如果 SF == 1,则传送 | SF == 1 |
18 | CMOVNS | 如果 SF == 0,则传送 | SF == 0 |
19 | CMOVP | 如果奇偶检验(parity),则传送 | PF == 1 |
20 | CMOVPE | 如果偶检验(parity even),则传送 | PF == 1 |
21 | CMOVNP | 如果不奇偶检验(not parity),则传送 | PF == 0 |
22 | CMOVPO | 如果奇检验(parity odd),则传送 | PF == 0 |
23 | CMOVL | 如果小于(less)则传送 | SF != OF |
24 | CMOVNGE | 如果不大于(not greater)或等于则传送 | SF != OF |
25 | CMOVNL | 如果不小于(not less)则传送 | SF == OF |
26 | CMOVGE | 如果大于(greater)或等于,则传送 | SF == OF |
27 | CMOVLE | 如果小于(less)或等于,则传送 | ZF == 1 || SF != OF |
28 | CMOVNG | 如果不大于(greater),则传送 | ZF == 1 || SF != OF |
29 | CMOVNLE | 如果不小于(not less)或等于,则传送 | ZF == 0 && SF == OF |
30 | CMOVG | 如果大于(greater),则传送 | ZF == 0 && SF == OF |