Memory Addressing

Part of Data Storage

How computers locate individual bytes in memory — address buses, address spaces, and the hardware that maps addresses to physical storage locations.

Why This Matters

A computer’s memory is useless unless each location can be uniquely identified and accessed. Memory addressing is the system by which the CPU specifies which byte it wants to read or write. Every instruction fetch, every data load, every stack push and pop is a memory access — and each one requires a valid address.

Understanding addressing is essential for anyone working with computer hardware. It determines how much memory a system can have, how peripherals share the same address space as RAM, and how operating systems protect one program’s memory from another. At the hardware level, address decoding is one of the first things you implement when building a computer from scratch.

The Address Bus

The CPU communicates with memory over an address bus — a set of parallel wires carrying the binary address of the location to be accessed. An N-bit address bus can address 2^N unique locations.

Common address bus widths:

  • 8-bit: 2^8 = 256 locations (used in simple microcontrollers)
  • 16-bit: 2^16 = 65,536 bytes = 64 KB (6502, Z80, 8080 CPUs)
  • 20-bit: 2^20 = 1 MB (Intel 8086 in real mode)
  • 24-bit: 2^24 = 16 MB (68000)
  • 32-bit: 2^32 = 4 GB (x86 32-bit)
  • 64-bit: 2^64 = 16 exabytes (x86-64, theoretical limit)

The address bus is unidirectional — the CPU drives addresses onto the bus, and memory responds. Data flows on a separate bidirectional data bus.

Address Decoding

A RAM chip typically has fewer address pins than the CPU’s address bus — a 64 KB RAM chip has 16 address pins, but a 1 MB system might have a 20-bit address bus. The upper address bits that go beyond the chip’s capacity are used for chip selection.

A decoder monitors the upper address bits and asserts the chip-select (CS) pin of whichever chip is being addressed:

  • Address 0x00000–0x0FFFF: select RAM chip 1 (lower 16 address bits go to chip)
  • Address 0x10000–0x1FFFF: select RAM chip 2
  • Address 0xE0000–0xFFFFF: select ROM chip

The decoder is typically a combinational circuit: AND/NAND gates that detect specific patterns on the upper address bits and drive active-low CS lines.

For a simple 2-chip system: if bit 15 = 0, assert CS for chip A; if bit 15 = 1, assert CS for chip B. One inverter and two buffers implement this.

Memory Map

The memory map is the table showing which addresses correspond to which physical device. In a typical 8-bit computer (16-bit address space):

Address RangeContents
0x0000–0x7FFF32 KB RAM
0x8000–0xBFFF16 KB RAM (expansion)
0xC000–0xDFFF8 KB I/O mapped peripherals
0xE000–0xFFFF8 KB ROM (OS/BIOS)

The CPU reset vector (the address of the first instruction after reset) is typically at the top of the ROM area. For the 6502, the reset vector is stored at addresses 0xFFFC–0xFFFD; the CPU reads those two bytes to determine where to start executing.

Designing the memory map is one of the first hardware design decisions for a custom computer. Reserve the top of address space for ROM (so reset works), place RAM at the bottom (for predictable addressing), and fill the middle with peripherals.

Memory-Mapped I/O vs. Port I/O

Two approaches to addressing peripherals:

Memory-mapped I/O: peripheral registers appear as addresses in the normal address space. The CPU accesses them with standard load/store instructions. Address decoding routes those addresses to the peripheral instead of RAM.

Port I/O: a separate address space accessed by dedicated IN and OUT instructions (8080, x86 architecture). Requires separate I/O address decoding logic and prevents use of standard memory instructions for peripheral access.

Memory-mapped I/O is simpler for custom hardware — no special instructions needed, and the decoder is just another address range. Most modern CPUs (ARM, RISC-V) use memory-mapped I/O exclusively.

Bank Switching

When the address bus is too narrow to address all available memory, bank switching allows addressing more memory than the address space would normally permit. The upper portion of address space is divided into “banks” that can be swapped by writing to a bank register.

The 8-bit 6502 with a 64 KB address space was expanded using bank switching. A control register holds the bank number. The upper 4 address bits from the CPU are replaced or combined with the bank number to generate the actual physical address, addressing up to 1 MB of physical memory despite only a 16-bit bus.

Bank switching complicates software (code must be aware of which bank is active) but was a practical necessity before 32-bit address buses.

Address Alignment

Many CPUs and memory systems require aligned accesses — 16-bit values must start at even addresses, 32-bit values at addresses divisible by 4, 64-bit at addresses divisible by 8. Misaligned accesses may be slower (require two bus cycles) or cause a hardware fault (on strict architectures like SPARC or early ARM).

Alignment matters because memory is often organized in banks of N bytes. A 32-bit memory bus accesses 4 bytes per cycle. If a 32-bit value starts at address 1 (not aligned to 4 bytes), two separate 4-byte reads are needed to collect the full value, with byte extraction and recombination — doubling access time.

For custom hardware design, always align data structures to their size. For structures in RAM, pad smaller fields so larger ones fall at aligned boundaries.