The Limitation: 64 KB Address Space

The Z80 uses 16-bit address lines, meaning it can only directly address 64 kilobytes (65,536 bytes) of memory (from address 0000H to FFFFH). Since many systems (like the MSX or larger Spectrums) have $128$ KB or more of RAM/ROM, they must use Memory Banking to access it all.

How Memory Banking Works

Memory Banking is the technique of using an I/O port to physically switch which $16$ KB or $8$ KB block of memory is visible to the CPU at a specific address range.

Example: A system might reserve the address range C000H to FFFFH for a switchable $16$ KB RAM bank. By writing a value (e.g., 00H, 01H, 02H) to the banking port, you can select RAM Bank 0, Bank 1, or Bank 2 to appear in that address range.

Switching Commands

Memory banking is always controlled by the standard Z80 OUT instruction.

Example: Switching RAM Banks Assume the banking port is 7FFDH (a common address on the ZX Spectrum).

BANKING_PORT EQU 7FFDH      ; The I/O port that controls the bank switch

SELECT_BANK_3:
    LD   A, 03H             ; Value 3 selects RAM Bank 3
    OUT  (BANKING_PORT), A  ; Write the value to the port

; RAM Bank 3 is now visible in the address range &C000H-&FFFFH.

SELECT_BANK_0:
    LD   A, 00H
    OUT  (BANKING_PORT), A  ; Switch back to RAM Bank 0
    RET

The ROM/RAM Dilemma

The operating system’s ROM (Read-Only Memory) always needs to be at the start of the address space (0000H) during startup. Once the OS is running, the CPU often switches the ROM out and replaces it with RAM so the user program can utilize that crucial low memory space.

Switching ROM/RAM: The banking port often has one specific bit dedicated to controlling the ROM/RAM swap for the 0000H–3FFFH address range. Setting that bit to 1 might enable RAM, and 0 might enable ROM.

Writing Bank-Aware Code: When writing modular assembly code, you must be extremely careful to ensure your code does not place its jump tables or data in a memory range that is about to be switched out by a banking command. Always check the target system’s memory map documentation!