Skip to content

6502 Addressing Modes Explained

Why Addressing Modes Matter

The 6510 processor in the Commodore 64 supports 13 addressing modes. Choosing the right one directly affects both code size and execution speed — critical when you have 19,656 cycles per raster frame and every cycle counts.

Immediate and Zero Page

Immediate (LDA #$05) loads a constant value. 2 bytes, 2 cycles.

Zero Page (LDA $FB) reads from addresses $00–$FF. 2 bytes, 3 cycles — one cycle faster than absolute addressing. The zero page is your most precious resource: use it for loop counters, pointers, and frequently accessed variables.

    ; Zero page pointer setup for indirect addressing
    LDA #<sprite_data
    STA $FB
    LDA #>sprite_data
    STA $FC

Absolute and Absolute Indexed

Absolute (LDA $D020) addresses the full 64K space. 3 bytes, 4 cycles. Absolute,X and Absolute,Y add an index register, costing an extra cycle if the addition crosses a page boundary.

Page-crossing penalties are critical in tight loops. The geo-referenced sprite technique aligns lookup tables to page boundaries specifically to avoid this overhead.

Zero Page Indexed

LDA $80,X wraps within zero page (address = ($80 + X) AND $FF). Useful for small arrays of game state. 2 bytes, 4 cycles — same cycle count as absolute but saves a byte, which matters when code size is tight.

Indirect Indexed and Indexed Indirect

These are the most powerful and most confusing modes:

Indirect Indexed (Y)LDA ($FB),Y: Takes the 16-bit pointer at $FB/$FC, adds Y to form the effective address. This is the workhorse for accessing data structures, screen memory, and sprite definitions. 2 bytes, 5+ cycles.

Indexed Indirect (X)LDA ($80,X): Uses X to select which zero-page pointer to dereference. Rarely used but powerful for jump tables and object dispatch — see how the Deep Winter sprite multiplexer uses it to manage variable sprite counts.

Relative Addressing

Branch instructions (BEQ, BNE, BCC, etc.) use signed 8-bit offsets, limiting jumps to -128/+127 bytes. A taken branch costs 3 cycles (4 if crossing a page). Structure your loops so the common case falls through and the rare case branches — it saves a cycle per iteration.

Implied and Accumulator

Single-byte instructions like TAX, RTS, CLC and accumulator operations like ASL A are the fastest at 2 cycles. The Seawolves engine uses chains of ASL/ROL for fast multiplication by powers of two, avoiding expensive lookup tables.

Practical Optimization

Profile your inner loops and promote any absolute memory access to zero page if the variable is used more than 3–4 times. Align tables to page boundaries to eliminate indexed crossing penalties. Use self-modifying code to turn indirect references into absolute ones where the address is known at setup time. These techniques are standard practice across all C64 development approaches.