Memory Addressing — The Full SIB Addressing Mode

x86-64 Assembly

Chapter 4 · Memory Addressing — The Full SIB Addressing Mode

Three courses, three addressing stories: LC-3's clean base+offset, the 6502's zero-page workaround, the Z80's displacement-based indexing. x86-64 doesn't pick one — it combines the ideas behind all of them into a single addressing mode genuinely richer than anything either prior course covered, plus one capability neither ever offered at all.

The Addressing Journey So Far

ArchitectureRichest addressing mode coveredAutomatic index scaling?
LC-3 (assembly1-3)Base+offset — a register plus a small constantNo
6502 (cpu8bit1-4)(zp),Y — a zero-page pointer plus an index registerNo
Z80 (cpu8bit1-7)(IX+d) — a register plus an 8-bit displacementNo
x86-64 (this chapter)Base + Index×Scale + Displacement, all in one instructionYes

The Full SIB Addressing Mode

x86-64's richest memory operand computes its effective address as:

effective address = Base + (Index × Scale) + Displacement
  • Base — any general-purpose register, holding a starting address, playing the same role as the Z80's own HL or the 6502's zero-page pointer.
  • Index — any general-purpose register, typically an array index.
  • Scale — a multiplier applied to Index, restricted to 1, 2, 4, or 8 — matching byte/word/dword/qword element sizes exactly.
  • Displacement — a constant offset, the same role LC-3's PC-relative offset and the Z80's own +d displacement played.
MOV RAX, [RBX + RCX*4 + 8]   ; RBX = array base, RCX = index, *4 for 4-byte elements, +8 skips a header

Why This Matters — No Manual Multiply Required

On the 6502 or Z80, indexing into an array of 4-byte elements would mean multiplying the index by 4 before the address could be computed — typically two shift-left operations, or repeated addition, as a separate step every single time. x86-64's Scale performs that exact multiplication as part of the address computation itself, inside the same instruction that actually accesses memory. This is a genuinely new capability, not just a faster version of something the earlier chips already did.

Scale is only 1, 2, 4, or 8 — nothing else
Need to index into an array of 3-byte or 5-byte elements? Scale can't do it directly — those values aren't legal scale factors. The multiply-for-free capability only covers the specific sizes that actually correspond to real data widths (byte/word/dword/qword). Anything else still needs a genuine, separate multiply instruction first, the same real limitation cpu8bit1-7's own warn-box already flagged for the Z80's own richer-but-not-unlimited addressing modes.

Not Every Component Is Required

Base, Index, Scale, and Displacement are all optional individually — an instruction only pays for the pieces it actually uses:

MOV RAX, [RBX]              ; base only — like Z80's own (HL)
MOV RAX, [RBX + 8]          ; base + displacement — like Z80's own (IX+d)
MOV RAX, [RBX + RCX]        ; base + index, scale defaults to 1
MOV RAX, [RBX + RCX*4 + 8]  ; all four components together

RIP-Relative Addressing — PC-Relative, Returned

x86-64 also added a genuinely new mode: [RIP + offset], computing an address relative to the current instruction pointer. This is conceptually the exact same idea as assembly1-3's own LC-3 PC-relative LD — but for a completely different, distinctly modern reason. LC-3 needed PC-relative addressing because a 16-bit instruction had no room for a full address at all. x86-64 doesn't have that bit-budget problem (assembly2-1's own variable-length instructions solve it) — RIP-relative addressing exists instead to support position-independent code: a program whose data references stay correct no matter where in memory the operating system actually loads it, a real security and shared-library requirement neither LC-3 nor the 6502/Z80 ever had to think about. The same underlying technique, reinvented decades later to solve an unrelated problem.

This is what the capstone will actually use
assembly2-12's own capstone leans directly on this chapter's full SIB mode — walking a real array using base+index×scale addressing in a single instruction is exactly the kind of concrete richness neither assembly1-10 nor cpu8bit1-12's own capstones had available to them.

Hands-On Exercises

Exercise 1

Given RBX (base) = 0x1000, RCX (index) = 5, a scale of 8, and a displacement of 16, compute the effective address of [RBX + RCX*8 + 16], showing your work.

📄 View solution
Exercise 2

Explain specifically what extra instruction(s) a 6502 or Z80 program would need, that an equivalent x86-64 program using Scale wouldn't, when indexing into an array of 8-byte elements.

📄 View solution
Exercise 3

Explain what RIP-relative addressing and LC-3's own PC-relative addressing (assembly1-3) have in common mechanically, and explain why each architecture actually needed it for a genuinely different reason.

📄 View solution

Chapter 4 Quick Reference

  • Effective address = Base + (Index × Scale) + Displacement — the richest single addressing mode across this whole three-course arc
  • Scale must be 1, 2, 4, or 8 — matching byte/word/dword/qword element sizes exactly; nothing else is directly supported
  • Scale performs index-multiplication as part of the address computation — the genuinely new capability neither the 6502 nor the Z80 offered
  • All four components (Base/Index/Scale/Displacement) are individually optional — an instruction only pays for what it uses
  • RIP-relative addressing — PC-relative addressing's conceptual return, now for position-independent code rather than a fixed-width instruction's bit budget
  • assembly2-12's capstone directly exercises SIB addressing for real array access