Skip to content
Lesson 3 of 5

Step 1 of 5 · Reading · ~4 min

Learn

Control Flow and Memory

Comparisons, Jumps, Loops

Assembly has no if, else, while or for. By the end of this lesson you can build all of them from two pieces, a comparison that sets flags and a jump that reads them, including a loop nested inside another loop.

Flags and cmp

The CPU keeps a few one-bit flags that arithmetic sets as a side effect: ZF (result was zero), SF (result was negative), CF (an unsigned borrow or carry happened) and OF (a signed overflow happened). cmp a, b computes a - b, throws the result away, and keeps only the flags.

For cmp rax, rbx with rax = 5 and rbx = 10, the difference is -5: SF = 1, CF = 1 (5 is below 10 as unsigned numbers too), ZF = 0, OF = 0. A conditional jump then reads those flags and either jumps to a label or falls through to the next line.

The jump family

QuestionSignedUnsigned
equal / not equalje, jneje, jne
less / greaterjl, jgjb (below), ja (above)
or equaljle, jgejbe, jae

jmp label always jumps. The signed and unsigned rows read different flags from the same cmp. With rax = -1, cmp rax, 0 makes jl taken (-1 < 0) but jb not taken, because as an unsigned number -1 is 0xFFFFFFFFFFFFFFFF. Counters and lengths are usually small and positive, so either works for them; pick signed unless you are comparing addresses or sizes.

test a, b ANDs its operands and keeps only the flags. test rax, rax sets ZF exactly when rax is 0, and test rax, 1 sets ZF exactly when the lowest bit is 0 (an even number).

A loop is a label and a backward jump

Put the check at the top, the body in the middle, and jmp back to the top. Here is a loop that sums 1 through 6 in a register:

    xor rax, rax            ; total
    mov rbx, 1              ; i
.add:
    cmp rbx, 6
    jg .end                 ; i > 6: leave
    add rax, rbx
    inc rbx
    jmp .add
.end:                       ; rax = 21
passi at the checktotal after the body
111
223
336
4410
5515
6621
exit721

Labels that start with a dot are local: .add belongs to the nearest global label above it, so several functions can each have a .end.

A loop inside a loop

The inner loop's counter must be set up again every time the outer loop comes around, so the setup goes inside the outer body. This counts the pairs (i, j) with 1 <= i < j <= 4, where the inner loop starts one past i:

    xor rax, rax            ; pair count
    mov r8, 1               ; i
.outer:
    cmp r8, 4
    jg .done
    lea r9, [r8 + 1]        ; j starts at i + 1
.inner:
    cmp r9, 4
    jg .next
    inc rax
    inc r9
    jmp .inner
.next:
    inc r8
    jmp .outer
.done:                      ; rax = 6

lea r9, [r8 + 1] computes r8 + 1 into r9 without touching the flags or r8. If the r9 setup sat above .outer, it would run once, and after the first pass the inner loop would be finished for good.

The counter that a syscall eats

syscall overwrites rcx and r11. A loop that keeps its counter in rcx and calls write inside the body loses the counter on every pass: rcx now holds the return address, a number around four million, so dec rcx / jnz repeats millions of times and floods the output. The x86 loop instruction has the same problem because it counts in rcx. Keep counters in rbx or r12 to r15, which every syscall preserves.

Common mistakes

  • Counter in rcx or r11 across a syscall. The loop runs far too long or ends early.
  • jge where jg was meant. cmp i, 6 then jge .end stops before handling 6.
  • Resetting nothing. An inner counter set up outside the outer loop leaves every row after the first empty.
  • Forgetting inc. The loop never ends and the run is killed for exceeding its time limit.

Your exercise

The starter reads a number into r12 and defines a star byte and a newline byte. Draw the shape the task describes with two loops. Choose registers that survive a syscall, and decide carefully what the inner loop compares against.

Up nextMemory and StringsControl Flow and Memory

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…