LAB-03Medium

Control Flow Tracing

Trace a short assembly routine step-by-step and determine the final register state and taken branch.

15 min5 prerequisites4 tools

Disassembly

start:
00:  mov rax, 0
01:  mov rcx, 5
02:  mov rdx, 0
loop:
03:  add rax, rcx
04:  sub rcx, 1
05:  cmp rcx, 0
06:  jne loop
done:
07:  mov rdx, rax
08:  ret 

Hints

Hint 1

RAX accumulates a running sum.

Hint 2

RCX starts at 5 and is decremented each iteration.

Hint 3

JNE jumps while the result is not equal to zero (ZF = 0).

Submit Findings

Prerequisites

  • a1-registers-movement
  • a2-arithmetic-logic
  • a3-control-flow
  • x64 register conventions (RAX, RCX, RDX)
  • Flags register (ZF, CF, SF, OF)

Methodology

Investigation Methodology

1. Understand the Routine Structure

  • Identify entry point (start label)
  • Find loop structure: label, body, condition, jump
  • Identify exit point (ret)

2. Register Initialization

  • mov rax, 0 — accumulator initialized to 0
  • mov rcx, 5 — loop counter initialized to 5
  • mov rdx, 0 — cleared (unused in loop, used at end)

3. Loop Analysis

Loop label at address 3:

  • add rax, rcx — add counter to accumulator
  • sub rcx, 1 — decrement counter
  • cmp rcx, 0 — compare counter to zero, sets flags
  • jne loop — jump if not equal (ZF=0)

4. Flag Behavior

  • cmp performs subtraction (RCX - 0) and sets flags, does not store result
  • ZF = 1 when result is zero (RCX == 0)
  • ZF = 0 when result non-zero (RCX != 0)
  • jne = Jump if Not Equal = Jump if ZF = 0

5. Iteration Trace

Iteration RAX (before) RCX (before) ADD result RCX (after SUB) CMP result JNE taken?
1 0 5 5 4 ≠0 (ZF=0) Yes
2 5 4 9 3 ≠0 (ZF=0) Yes
3 9 3 12 2 ≠0 (ZF=0) Yes
4 12 2 14 1 ≠0 (ZF=0) Yes
5 14 1 15 0 =0 (ZF=1) No

6. Post-Loop

  • Loop exits when RCX = 0, ZF = 1
  • mov rdx, rax — copy final sum (15) to RDX
  • ret — return with RAX = 15, RDX = 15

Common Pitfalls

  • Thinking the loop runs 6 times (0 through 5) — it runs 5 times (5 down to 1)
  • Confusing `jne` (jump if ZF=0) with `je` (jump if ZF=1)
  • Forgetting `cmp` doesn't modify registers, only flags
  • Missing that the final iteration adds 1 (when RCX=1), not 0

Tools

  • Assembly Visualizer (built-in)
  • Ghidra decompiler (to verify logic)
  • x64dbg / GDB (step through manually)
  • Pen and paper (register trace table)

References

  • Lesson A2: Arithmetic & Logic — ADD, SUB, CMP
  • Lesson A3: Control Flow — JNE, JE, JG, JL
  • Intel SDM Vol 2: CMP, Jcc instructions
  • x64 Calling Convention — RAX return value

Extensions & Challenges

  • Modify the loop to sum 1..10 (change RCX initial value)
  • Convert to a `while` loop structure (check at top)
  • Add a second nested loop
  • Research: How does the compiler optimize this loop? (e.g., `lea` + `loop` instruction)