Memory Mapping
Addresses for everything
Memory-mapped I/O places hardware registers at specific addresses, allowing software to control graphics, sound, and input by reading and writing memory locations.
Overview
Memory mapping assigns specific memory addresses to hardware registers, allowing programs to control peripherals through normal load/store operations rather than special I/O instructions. This approach defined how programmers interacted with 8-bit and 16-bit hardware.
Examples
Commodore 64:
$D000-$D3FF: VIC-II graphics chip (47 registers + mirrors)$D400-$D7FF: SID sound chip (29 registers + mirrors)$D800-$DBFF: colour RAM (1 KB, 4-bit-wide chip)$DC00-$DCFF: CIA#1 (keyboard, joystick, IRQ source)$DD00-$DDFF: CIA#2 (serial bus, RS-232, NMI source, VIC bank select)
NES:
$2000-$2007: PPU registers (mirrored every 8 bytes through$3FFF)$4000-$4017: APU and I/O ($4014 = OAMDMA, $4016/$4017 = controllers)
Amiga:
$DFF000-$DFF1FE: custom chip registers (Agnus, Denise, Paula, Copper, Blitter)$BFE001: CIA-A PRA (joystick fire buttons, parallel port)$BFD000: CIA-B (serial port, disk control, mouse)
Memory-mapped vs port-mapped I/O
Most 8-bit and 16-bit systems use memory-mapped I/O — hardware registers live in the same address space as RAM, accessed by normal LDA/STA (or equivalent). The 6502, 6510, 6809, and 68000 have no separate I/O instructions, so memory mapping is the only option.
The Z80 is different: it has dedicated IN and OUT instructions that access a separate I/O port address space (256 ports on a basic Z80, 65,536 with the indirect form). The ZX Spectrum, Amstrad CPC, MSX, and Z80-based arcade boards all use port-mapped I/O for hardware control. Memory-mapped accesses to the same hardware on those systems would require dedicated address decoding and aren't typically used.
Hybrid systems (like Sega Master System with Z80 + memory-mapped VDP) place graphics in memory space but sound in port space, mixing both styles.
Programming Model
; C64: Set border colour to black
LDA #$00
STA $D020 ; Border colour register
; C64: Set volume
LDA #$0F
STA $D418 ; SID volume register
Advantages
- Consistent programming model
- Works with all CPU instructions
- No special I/O instructions needed
- Debuggers can monitor register access