Skip to main content
← All posts

Part 8: Conditional Branching, Jump Instructions & Fast Loops in Assembly

Md. Harun-Or-RoshidNov 5, 20263 min readArticle
Part 8: Conditional Branching, Jump Instructions & Fast Loops in Assembly

Lesson Overview & Control Flow

At the hardware level, processors execute instructions sequentially unless directed otherwise by control-flow instructions. In assembly language, high-level constructs like if-else, switch-case, while, and for loops dissolve into comparisons, flag evaluations, and conditional jump instructions. In Part 8, we master the CMP instruction, dissect signed vs. unsigned conditional jumps, construct robust loop structures, explore CPU branch prediction mechanics, and utilize branchless conditional moves (CMOV).

1. The CMP Instruction and Flag Evaluation

The primary comparison instruction is CMP operand1, operand2. Mechanically, CMP performs an internal subtraction: temp = operand1 - operand2. It updates the condition flags (ZF, CF, SF, OF) identically to SUB, but discards the numerical result, leaving the destination operand unmodified.

2. Signed vs. Unsigned Conditional Jumps

A critical distinction in x86-64 assembly is choosing the correct jump instruction based on whether your data represents signed (two's complement) or unsigned integers:

CategoryJump MnemonicConditionTested Flags
Equality (Universal)JE / JZ JNE / JNZJump if Equal (Zero) Jump if Not Equal (Not Zero)ZF = 1 ZF = 0
Signed ComparisonJG / JNLE JGE / JNL JL / JNGE JLE / JNGJump if Greater (>) Jump if Greater or Equal (≥) Jump if Less (<) Jump if Less or Equal (≤)ZF = 0 and SF = OF SF = OF SF ≠ OF ZF = 1 or SF ≠ OF
Unsigned ComparisonJA / JNBE JAE / JNB JB / JNAE JBE / JNAJump if Above (> unsigned) Jump if Above or Equal (≥) Jump if Below (< unsigned) Jump if Below or Equal (≤)CF = 0 and ZF = 0 CF = 0 CF = 1 CF = 1 or ZF = 1

3. Writing Efficient Loop Structures: Why Avoid LOOP?

Historically, x86 featured the LOOP target instruction, which decremented RCX and jumped if RCX != 0. However, on modern out-of-order processors, LOOP has high micro-op decode latency and poor silicon execution port dispatch.

Modern assembly engineers and optimizing compilers construct loops using standard decrement and jump instructions:

; High-performance 64-bit loop: Sum elements from 100 down to 1

mov rcx, 100 ; Iteration counter

xor rax, rax ; Accumulated sum


.loop_body:

add rax, rcx ; sum += counter

sub rcx, 1 ; Decrement counter and update ZF

jnz .loop_body ; Jump back if RCX != 0

4. Branch Prediction & Branchless CMOV (Conditional Move)

CPUs use speculative execution and branch predictors to guess whether a jump will occur before the condition flag is even computed. When a branch predictor mispredicts, the entire instruction pipeline must be flushed, costing 15 to 20 clock cycles of latency!

To eliminate branch penalties for simple assignments (such as min(a, b) or abs(x)), modern processors provide the Conditional Move (CMOVcc) instruction:

; Branchless Minimum: RAX = min(RAX, RBX)

cmp rax, rbx

cmovg rax, rbx ; If RAX > RBX (signed), overwrite RAX with RBX without jumping!

Summary & Next Step

With conditional jumps and loops mastered, we can process large data structures. In Part 9, we explore array indexing patterns, multidimensional matrix stride math, and hardware-accelerated block memory primitives (REP MOVSB, STOSB, LODSB).

Share:
Share on X
Share on LinkedIn
Share on Facebook
Share on Reddit
Share on WhatsApp
Share on Telegram
Copy link

Related reading

Branching, Jumps & Loops in x86-64 Assembly | Draftsbook · Draftsbook