Intel x86 Assembly Language & Microarchitecture Conditional jumps


Example

Based on the state of the flags the CPU can either execute or ignore a jump. An instruction that performs a jump based on the flags falls under the generic name of Jcc - Jump on Condition Code1.

Synonyms and terminology

In order to improve the readability of the assembly code, Intel defined several synonyms for the same condition code. For example, jae, jnb and jnc are all the same condition code CF = 0.

While the instruction name may give a very strong hint on when to use it or not, the only meaningful approach is to recognize the flags that need to be tested and then choose the instructions appropriately.
Intel however gave the instructions names that make perfect sense when used after a cmp instruction. For the purposes of this discussion, cmp will be assumed to have set the flags before a conditional jump.

Equality

The operand are equal iff ZF has been set, they differ otherwise. To test for equality we need 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)
InstructionFlags
je, jzZF = 1
jne, jnzZF = 0

Greater than

For unsigned operands, the destination is greater than the source if carry was not needed, that is, if CF = 0. When CF = 0 it is possible that the operands were equal, testing ZF will disambiguate.

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)
InstructionFlags
jae, jnc, jnbCF = 0
ja, jnbeCF = 0, ZF = 0

For signed operands we need to check that SF = 0, unless there has been a signed overflow, in which case the resulting SF is reversed. Since OF = 0 if no signed overflow occurred and 1 otherwise, we need to check that SF = OF.

ZF can be used to implement a strict/non strict test.

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)
InstructionFlags
jge, jnlSF = OF
jg, jnleSF = OF, ZF = 0

Less than

These use the inverted conditions of above.

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)
InstructionFlags
jbe, jnaCF = 1 or ZF = 1
jb, jc, jnaeCF = 1
jle, jngSF != OF or ZF = 1
jl, jngeSF != OF

Specific flags

Each flag can be tested individually with j<flag_name> where flag_name does not contain the trailing F (for example CFC, PFP).

The remaining codes not covered before are:

InstructionFlag
jsSF = 1
jnsSF = 0
joOF = 1
jnoOF = 0
jp, jpe (e = even)PF = 1
jnp, jpo (o = odd)PF = 0

One more conditional jump (extra one)

One special x86 conditional jump doesn't test flag. Instead it does test value of cx or ecx register (based on current CPU address mode being 16 or 32 bit), and the jump is executed when the register contains zero.

This instruction was designed for validation of counter register (cx/ecx) ahead of rep-like instructions, or ahead of loop loops.

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)
InstructionRegister (not flag)
jcxz, jecxzcx = 0 (16b mode)
jcxz, jecxzecx = 0 (32b mode)

1 Or something like that.