.text:004081D0; =============== S U B R O U T I N E ===============
.text:004081D0
.text:004081D0

x86-64 registers and flags, the parts that matter

.text:004081D0; author: Can Ozdemir date: 2024-06-22 size: 0xDE0 tags: x86-64, basics, tutorial
.text:004081D0
.text:004081D0sub_4081D0procnear
.text:004081D1

You don't need the whole Intel manual to read disassembly. You need the sixteen general-purpose registers, a handful of flags, and how comparisons drive jumps.

.text:00408270

The general-purpose registers

.text:00408290

There are sixteen 64-bit registers: rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, and r8 to r15. Each can also be used at smaller sizes:

.text:00408326
64-bit   32-bit   16-bit   8-bit
rax      eax      ax       al
rcx      ecx      cx       cl
rsi      esi      si       sil
rsp      esp      sp       spl
r8       r8d      r8w      r8b
.text:004083DF

The others follow the same pattern. Some have traditional roles: rsp is the stack pointer, rbp is often the frame pointer, rax holds return values, rcx is a counter for string and shift instructions. In the System V calling convention, arguments arrive in rdi, rsi, rdx, rcx, r8, r9.

.text:0040850E

rip is the instruction pointer. You never move into it directly, but you'll see it constantly as [rip+0x2fca]: position-independent code addressing data relative to the current instruction.

.text:004085CF

The zero-extension rule

.text:004085E9

This one surprises people:

.text:00408603
  • writing a 32-bit register clears the upper 32 bits of the 64-bit register: mov eax, 1 leaves rax = 1
  • writing an 8- or 16-bit register leaves the other bits alone: mov al, 1 changes only the lowest byte
.text:004086DF

That's why compilers happily use mov eax, edi or xor eax, eax even for 64-bit values: they are shorter to encode, and the upper half is zeroed for free. It's also why mov edi, edi appears in jump-table code: it's a zero-extension, not a no-op.

.text:004087D8

Flags

.text:004087E0

Arithmetic instructions set bits in the rflags register. Four matter for reading code:

.text:00408838
  • ZF, zero flag: the result was zero
  • SF, sign flag: the result's top bit was set (negative, if signed)
  • CF, carry flag: an unsigned overflow or borrow happened
  • OF, overflow flag: a signed overflow happened
.text:0040891B

cmp and test

.text:0040892A

Two instructions exist only to set flags:

.text:00408953
  • cmp a, b computes a - b, sets flags, and throws the result away
  • test a, b computes a & b, sets flags, and throws the result away
.text:004089E0

test eax, eax is the idiomatic "is eax zero / negative?": ANDing a value with itself sets ZF if it's zero and SF if its top bit is set.

.text:00408A69

Conditional jumps

.text:00408A7D

After a cmp a, b, the jump tells you how the program compared them:

.text:00408AC2
je  / jz     a == b              ZF = 1
jne / jnz    a != b              ZF = 0
jl  / jnge   a <  b   signed     SF != OF
jle          a <= b   signed     ZF = 1 or SF != OF
jg           a >  b   signed     ZF = 0 and SF = OF
jge          a >= b   signed     SF = OF
jb  / jc     a <  b   unsigned   CF = 1
jbe          a <= b   unsigned   CF = 1 or ZF = 1
ja           a >  b   unsigned   CF = 0 and ZF = 0
jae / jnc    a >= b   unsigned   CF = 0
js / jns     result negative / not negative
.text:00408CAD

The mnemonic gives away the type: l/g (less/greater) are signed, b/a (below/above) are unsigned. If you see ja after comparing an index with a bound, the index is unsigned, which is exactly the check a switch statement compiles to.

.text:00408DA0

The same conditions appear in setcc (store 0/1 into a byte, like sete al) and cmovcc (conditional move, like cmovle eax, edi). Same suffixes, same meanings.

.text:00408E44

A worked line

.text:00408E54
cmp  DWORD PTR [rbp-0x4], 0xff
jle  0x24
.text:00408E7C

"If the local at rbp-0x4 is less than or equal to 255, signed, jump to 0x24." Translating each cmp + jcc pair into one sentence like this is most of the work of reading control flow.

.text:00408F3A
.text:00408F3Aretn
.text:00408F3Asub_4081D0endp
.text:00408F3A; © 2026 Can Ozdemir. All rights reserved. terms
.text:00408F3A
.text:00408F3B; -------- cross references --------
Output
Loading ozdc.us… 34 functions, 3 data segments.
Type help in the command line below and press Enter.