The Z80 chip also supports indirect addressing, which is different from immediate and direct modes. This is used when data is not stored directly in the instruction, but instead in the memory location pointed to by a register pair.
In this mode, instead of specifying an explicit memory address, we load from or store to the address held in a register pair, such as HL, BC, or DE.
This is especially useful when working with memory blocks, moving data, or performing pointer-style operations.
The Z80 provides several variations of indirect addressing. Here's a breakdown of key forms:
We can use indirect mode to store multiple values to memory without writing explicit addresses.
ORG 256
LD BC,35900 ; Start address for storing
LD A,65 ; ASCII code for 'A'
LD (BC),A ; Store 'A' at BC
INC BC
LD (BC),A ; Store 'A' at next byte
INC BC
LD (BC),A ; Store 'A' at next byte
This stores three A characters into memory starting at address 35900.
ORG 256
LD BC,35900 ; Pointer to memory
LD A,65 ; ASCII for 'A'
LD E,3 ; Number of times to store
NXT: LD (BC),A ; Store A
INC BC ; Move pointer forward
DEC E ; Decrement counter
JR NZ,NXT ; Repeat until E = 0
This version is shorter and clearer, using a loop to perform repeated indirect memory writes.
To see indirect addressing in action, let’s build a program that stores a short message in memory, then reads and prints it one character at a time using a pointer.
This simulates how a real system might walk through a string or data block stored in RAM.
LD (HL),AINC HL(HL) as a dynamic pointer ORG 256
LD HL,30000 ; Point to where we'll store the string
LD A,'H'
LD (HL),A ; Store 'H'
INC HL
LD A,'I'
LD (HL),A ; Store 'I'
INC HL
LD A,0 ; Null terminator (optional for stopping later)
LD (HL),A
; Reset pointer to start of string
LD HL,30000
READ: LD A,(HL) ; Load character from memory
CP 0
RET Z ; End of string
CALL PRINT
INC HL
JR READ
PRINT: RST 8
DEFB 158 ; MCAL print character in A
RET
HL walks through the memory where the string is stored.CP 0 and RET Z stop the loop at the null terminator.RST 8 / DEFB 158).This method mimics how real operating systems, firmware, or BIOS routines process:
Indirect addressing provides a powerful, general-purpose way to walk through data structures without hardcoding every address.
Surely there’s an easier way to store a string of characters? Absolutely, and in fact, assembly provides several ways to make this more convenient.
Here’s one of the simplest:
message:
DEFB 'HELLO WORLD',0
or
message:
DB 'HELLO WORLD',0
This uses an assembler directive, not a Z80 CPU instruction. DB stands for Define Byte, and it tells the assembler to place the individual ASCII values for each character (including the null terminator 0) directly into memory at the current location.
This approach allows you to define entire strings inline with your code, and the assembler handles turning them into the correct bytes.
HL, BC, DEExercise 4.1
Write a program that stores the values 1 to 5 in consecutive memory locations using indirect mode and a loop.
Exercise 4.2
Explain what the following code does and why indirect mode is used:
LD HL,40000
LD A,(HL)
INC HL
LD A,(HL)