汇编语言条件跳转指令汇总


x86 指令集包含大量的条件跳转指令。它们能比较有符号和无符号整数,并根据单个 CPU 标志位的值来执行操作。条件跳转指令可以分为四个类型:
  • 基于特定标志位的值跳转
  • 基于两数是否相等,或是否等于(E)CX 的值跳转
  • 基于无符号操作数的比较跳转
  • 基于有符号操作数的比较跳转

下表展示了基于零标志位、进位标志位、溢出标志位、奇偶标志位和符号标志位的跳转。

助记符 说明 标志位/寄存器 助记符 说明 标志位/寄存器
JZ 为零跳转 ZF=1 JNO 无溢出跳转 OF=0
JNZ 非零跳转 ZF=0 JS 有符号跳转 SF=1
JC 进位跳转 CF=1 JNS 无符号跳转 SF=0
JNC 无进位跳转 CF=0 JP 偶校验跳转 PF=1
JO 溢出跳转 OF=1 JNP 奇校验跳转 PF=0

1) 相等性的比较

下表列出了基于相等性评估的跳转指令。有些情况下,进行比较的是两个操作数;其他情况下,则是基于 CX、ECX 或 RCX 的值进行跳转。表中符号 leftOp 和 rightOp 分别指的是 CMP 指令中的左(目的)操作数和右(源)操 作数:

助记符 说明
JE 相等跳转 (leftOp=rightOp)
JNE 不相等跳转 (leftOp M rightOp)
JCXZ CX=0 跳转
JECXZ ECX=0 跳转
JRCXZ RCX=0 跳转(64 位模式)

CMP leftOp,rightOp

操作数名字反映了代数中关系运算符的操作数顺序。比如,表达式 X< Y 中,X 被称为 leftOp,Y 被称为 rightOp。

尽管 JE 指令相当于 JZ(为零跳转),JNE 指令相当于 JNZ(非零跳转),但是,最好是选择最能表明编程意图的助记符(JE 或 JZ),以便说明是比较两个操作数还是检查特定的状态标志位。

下述示例使用了 JE、JNE、JCXZ 和 JECXZ 指令。仔细阅读注释,以保证理解为什么条件跳转得以实现(或不实现)。

示例 1:

mov edx, 0A523h
cmp edx, 0A523h
jne L5                       ;不发生跳转
je L1                         ;跳转

示例 2:

mov bx,1234h
sub bx,1234h
jne L5                       ;不发生跳转
je L1                         ;跳转

示例 3:

mov ex, 0FFFFh
inc ex
jexz L2                      ;跳转

示例4:

xor ecx,ecx
jeexz L2                   ;跳转

2) 无符号数比较

基于无符号数比较的跳转如下表所示。操作数的名称反映了表达式中操作数的顺序(比如 leftOp < rightOp)。下表中的跳转仅在比较无符号数值时才有意义。有符号操作数使用不同的跳转指令。

助记符 说明 助记符 说明
JA 大于跳转(若 leftOp > rightOp) JB 小于跳转(若 leftOp < rightOp)
JNBE 不小于或等于跳转(与 JA 相同) JNAE 不大于或等于跳转(与 JB 相同)
JAE 大于或等于跳转(若 leftOp ≥ rightOp) JBE 小于或等于跳转(若 leftOp ≤ rightOp)
JNB 不小于跳转(与 JAE 相同) JNA 不大于跳转(与 JBE 相同)

3) 有符号数比较

下表列岀了基于有符号数比较的跳转。下面的指令序列展示了两个有符号数值的比较:

助记符 说明 助记符 说明
JG 大于跳转(若 leftOp > rightOp) JL 小于跳转(若 leftOp < rightOp)
JNLE 不小于或等于跳转(与 JG 相同) JNGE 不大于或等于跳转(与 JL 相同)
JGE 大于或等于跳转(若 leftOp ≥ rightOp) JLE 小于或等于跳转(若 leftOp ≤ rightOp)
JNL 不小于跳转(与 JGE 相同) JNG 不大于跳转(与 JLE 相同)

mov al, +127             ;十六进制数值 7Fh
cmp al, -128              ;十六进制数值 80h
ja Is Above                ;不跳转,因为 7Fh < 80h
jg IsGreater               ;跳转,因为 +127 > -128

由于无符号数 7Fh 小于无符号数 80h,因此,为无符号数比较而设计的 JA 指令不发生跳转。另一方面,由于 +127 大于 -128,因此,为有符号数比较而设计的 JG 指令发生跳转。

对下面的代码示例,阅读注释,以保证理解为什么跳转得以实现(或不实现):

示例 1:

mov edx,-1
cmp edx, 0
jnl  L5                   ;不发生跳转(-1 ≥ 0 为假)
jnle L5                  ;不发生跳转(-1 > 0 为假)
jl L1                      ;跳转(-1 < 0 为真)

示例 2:

mov bx,+ 32
cmp bx,-35
jng L5                 ;不发生跳转( + 32 ≤ -35 为假)
jnge L5               ;不发生跳转( + 32 < -35 为假)
jge L1                 ;跳转( + 32 ≥ -35 为真)

示例 3:

mov ecx, 0
cmp ecx, 0
jg L5                     ;不发生跳转(0 > 0 为假)
jnl L1                    ;跳转(0 ≥ 0 为真)

示例 4:

mov ecx, 0
cmp ecx, 0
jl L5                      ;不发生跳转(0 < 0 为假)
jng L1                   ;跳转(0 ≤ 0 为真)