Z80 Addressing Modes and the Stack

8-Bit CPUs — 6502/6510 & Z80

Chapter 7 · Z80 Addressing Modes and the Stack

This closes out the Z80 block. cpu8bit1-6 previewed IX/IY and HL-as-pointer; this chapter delivers the full addressing-mode picture, including the real cost the Z80's flexibility carries — and finishes with the stack, where the Z80 turns out to be a genuine synthesis of what LC-3 and the 6502 each did separately.

Register-Indirect Addressing — (HL), (BC), (DE)

cpu8bit1-6 already introduced (HL) as a direct pointer dereference. (BC) and (DE) work identically in principle — reading or writing whatever address the register pair currently holds — though in practice they're supported by a narrower set of instructions (mainly simple loads and stores), while HL remains the chip's general-purpose pointer workhorse, usable with far more of the instruction set. All three are simpler than assembly1-3's own LC-3 indirect mode (LDI), which required a two-step "read a pointer from a PC-relative address, then follow it" — here, the pointer already sits directly in a register, one step only.

Indexed Addressing With Displacement — IX+d and IY+d

IX and IY support a genuinely powerful addressing mode: a base register plus a signed 8-bit displacement (d, roughly -128 to +127), computed at execution time:

LD IX, $4000
LD A, (IX+5)   ; reads the byte at $4000 + 5 = $4005

This is a natural fit for accessing individual fields of a data structure at fixed offsets from a base pointer — IX holding the structure's address, d selecting which field — and unlike the 6502's own indexed modes from cpu8bit1-4, it isn't tied to zero page at all. IX and IY can point anywhere in the full 64KB space.

That flexibility has a real, measurable cost. Recall cpu8bit1-4's own cycle table for the 6502's addressing modes:

ChipInstructionCyclesNotes
Z80LD A,(HL)7Direct register-pointer dereference
Z80LD A,(IX+d)19Prefix byte + opcode + displacement byte, plus real address-calculation time
6502LDA zero page3cpu8bit1-4
6502LDA (zp),Y5cpu8bit1-4 — the closest 6502 equivalent to a flexible pointer-plus-offset read

LD A,(IX+d) costs nearly four times what (HL) costs, and almost four times what the 6502's own (zp),Y costs for a broadly comparable "pointer plus offset" access. The Z80's version can reach anywhere in memory rather than needing a zero-page base — but that extra reach is paid for in real, per-instruction cycles, not just extra transistors.

Richness has a price, and it isn't only transistors
cpu8bit1-5 and cpu8bit1-6 both measured the Z80's richness in transistor count. This is the same story showing up at runtime instead of at manufacturing time — IX/IY addressing genuinely does more, but every use of it costs real, measurable extra cycles compared to the chip's own simpler modes. A capability existing isn't the same as it being free to use.

The Stack — Real Hardware, Genuinely Flexible

cpu8bit1-3 covered the 6502's real but page-1-locked hardware stack, itself a genuine improvement over assembly1-7's entirely software-built LC-3 stack. The Z80's stack is a third point on that same spectrum: SP is a full 16-bit register, free to point anywhere in the 64KB address space — no fixed page, no artificial ceiling.

Push and pop are native instructions, and — reflecting cpu8bit1-6's own register pairing — they operate on a full 16-bit register pair at once, not a single byte the way the 6502's PHA does:

PUSH BC   ; pushes both B and C together, 16 bits in one instruction
POP  BC   ; pulls both back

The stack still grows downward — SP decrements on every push — the same convention assembly1-7's own LC-3 example and cpu8bit1-3's 6502 stack both already used.

ArchitectureWhere the stack can liveHardware supportPush/pop granularity
LC-3 (assembly1-7)Anywhere in memory — the programmer's own choiceNone — manually built from ADD/STR/LDROne value at a time, via generic instructions
6502 (cpu8bit1-3)Locked to page 1 only ($0100–$01FF)Real — dedicated SP register, PHA/PLA/PHP/PLPOne byte at a time
Z80 (this chapter)Anywhere in the full 64KB spaceReal — dedicated 16-bit SP register, PUSH/POPOne 16-bit register pair at a time

Put side by side, the Z80's stack genuinely combines the best of both predecessors covered so far: LC-3's freedom to live anywhere, with real dedicated hardware doing the actual work — the flexibility of a software stack with the speed of a hardware one.

Next: putting all of this to work
Every addressing mode and stack mechanism from both this chapter and Chapters 2–4 gets used for real in cpu8bit1-8, which implements one identical routine in both 6502 and Z80 assembly, side by side — the course's first direct, concrete payoff of studying the two chips in parallel rather than in isolation.

Hands-On Exercises

Exercise 1

Given IX = $4000, compute the effective address of LD A,(IX+5) using this chapter's own formula, and show your work.

📄 View solution
Exercise 2

Using this chapter's own cycle table, explain why LD A,(IX+d) (19 cycles) costs almost four times as much as the 6502's own LDA (zp),Y (5 cycles), even though both are broadly "flexible pointer plus offset" addressing modes.

📄 View solution
Exercise 3

Using this chapter's own three-way stack comparison table, explain what each of LC-3, the 6502, and the Z80 trades away in exchange for its own particular combination of flexibility and hardware support.

📄 View solution

Chapter 7 Quick Reference

  • (HL)/(BC)/(DE) — direct register-pointer dereference, simpler than LC-3's own two-step LDI
  • IX+d / IY+d — a base register plus a signed 8-bit displacement, reaching anywhere in the full 64KB space
  • LD A,(IX+d) costs 19 cycles vs. (HL)'s 7 and the 6502's own (zp),Y at 5 — flexibility has a real runtime cost, not just a transistor one
  • The Z80's SP is a full 16-bit register — the stack can live anywhere in memory, with no page restriction
  • PUSH/POP move a full 16-bit register pair in one instruction, vs. the 6502's single-byte PHA/PLA
  • Three-way stack comparison: LC-3 (flexible, software-only) → 6502 (hardware, page-locked) → Z80 (hardware AND flexible)
  • This closes the Z80 block — cpu8bit1-8 puts every addressing mode and stack mechanic from both chips to work side by side