有条件的跳跃
根据标志的状态,CPU 可以执行或忽略跳转。基于标志执行跳转的指令属于 Jcc 的通用名称 - 条件代码 1 上的跳转。
同义词和术语
为了提高汇编代码的可读性,英特尔为相同的条件代码定义了几个同义词。例如,jae,jnb 和 jnc 都是相同的条件代码 CF = 0 。
虽然指令名称可能会对何时使用它给出非常强烈的暗示,但唯一有意义的方法是识别需要测试的标志然后适当地选择指令。
然而,英特尔给出了在 cmp 指令之后使用时非常有意义的指令名称。出于本讨论的目的,假设 cmp 在条件跳转之前设置了标志。
相等
如果设置了 *ZF,*则操作数相等,否则它们不同。为了测试相等性,我们需要 ZF = 1 。
je a_label ;Jump if operands are equal
jz a_label ;Jump if zero (Synonym)
jne a_label ;Jump if operands are NOT equal
jnz a_label ;Jump if not zero (Synonym)
| 指令 | 标志 |
|---|---|
je,jz |
ZF = 1 |
jne,jnz |
ZF = 0 |
比…更棒
对于无符号操作数,如果不需要进位,则目标大于源,即 CF = 0 时。当 CF = 0 时,操作数可能相等,测试 ZF 将消除歧义。
jae a_label ;Jump if above or equal (>=)
jnc a_label ;Jump if not carry (Synonym)
jnb a_label ;Jump if not below (Synonym)
ja a_label ;Jump if above (>)
jnbe a_label ;Jump if not below and not equal (Synonym)
| 指令 | 标志 |
|---|---|
jae,jnc,jnb |
CF = 0 |
ja,jnbe |
CF = 0,ZF = 0 |
对于带**符号的操作数,**我们需要检查 SF = 0 ,除非有符号溢出,在这种情况下产生的 SF 反转。由于 *OF = 0,*如果没有发生签名溢出,否则为 1,我们需要检查 SF = OF 。
ZF 可用于实施严格/非严格测试。
jge a_label ;Jump if greater or equal (>=)
jnl a_label ;Jump if not less (Synonym)
jg a_label ;Jump if greater (>)
jnle a_label ;Jump if not less and not equal (Synonym)
| 指令 | 标志 |
|---|---|
jge,jnl |
SF = OF |
jg,jnle |
SF = OF,ZF = 0 |
少于
这些使用上述的反转条件。
jbe a_label ;Jump if below or equal (<=)
jna a_label ;Jump if not above (Synonym)
jb a_label ;Jump if below (<)
jc a_label ;Jump if carry (Synonym)
jnae a_label ;Jump if not above and not equal (Synonym)
;SIGNED
jle a_label ;Jump if less or equal (<=)
jng a_label ;Jump if not greater (Synonym)
jl a_label ;Jump if less (<)
jnge a_label ;Jump if not greater and not equal (Synonym)
| 指令 | 标志 |
|---|---|
jbe,jna |
CF = 1 或 ZF = 1 |
jb,jc,jnae |
CF = 1 |
jle,jng |
SF != OF 或 ZF = 1 |
jl,jnge |
SF != OF |
具体标志
可以使用 j<flag_name> 单独测试每个标志,其中 flag_name 不包含尾随 F (例如 CF → C , PF → P )。
以前未涉及的其余代码是:
| 指令 | 标志 |
|---|---|
js |
SF = 1 |
jns |
SF = 0 |
jo |
OF = 1 |
jno |
OF = 0 |
jp,jpe(e = even) |
PF = 1 |
jnp,jpo(o = odd) |
PF = 0 |
还有一个条件跳转(额外的一个)
一个特殊的 x86 条件跳转不会测试标志。相反,它测试 cx 或 ecx 寄存器的值(基于当前 CPU 地址模式为 16 或 32 位),并且当寄存器包含零时执行跳转。
该指令设计用于在类似于 rep 的指令之前或者在 loop 循环之前验证计数器寄存器(cx/ecx)。
jcxz a_label ; jump if cx (16b mode) or ecx (32b mode) is zero
jecxz a_label ; synonym of jcxz (recommended in source code for 32b target)
| 指令 | 注册(不是标志) |
|---|---|
jcxz,jecxz |
cx = 0(16b 模式) |
jcxz,jecxz |
ecx = 0(32b 模式) |
1 或类似的东西。