有条件的跳跃
根据标志的状态,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 或类似的东西。