6502: The People's Processor
Eight bits that changed everything
The MOS 6502 powered the Apple II, Atari 2600, Commodore 64, and NES—making home computing affordable and defining a generation of programmers.
The MOS 6502, designed by Chuck Peddle and released in 1975, democratised computing. At $25 when competitors charged $300+, it made personal computers financially viable. Its elegant instruction set and zero-page addressing made assembly programming accessible to bedroom coders worldwide.
Fast facts
- Clock speed: typically 1-2 MHz depending on system.
- Data bus: 8-bit with 16-bit address bus (64KB addressable).
- Registers: accumulator (A), two index registers (X, Y), stack pointer, status register.
- Zero page: first 256 bytes ($00-$FF) accessed with single-byte addresses for speed.
- Stack: fixed at $0100-$01FF, grows downward.
Why zero page is fast
Zero page is usually explained as “one byte shorter”. MOS’s own manual explains it as one cycle shorter, and says where the cycle goes.
An absolute access needs three bytes and four cycles: opcode, address low, address high, data. A zero-page access needs two and three — and the reason is that the processor works out what kind of instruction it is holding before it has finished reading the operand:
by the end of the second cycle, the microprocessor has decoded the fact that this is a zero page operation and on the next cycle, it outputs address 00, as the effective address high, along with the address low that it just fetched
The high byte is never fetched because the processor already knows it is zero. A quarter of every memory access saved, for the price of confining your variables to the first 256 bytes — and MOS says outright that this is how the chip is meant to be used: “the user should organize his memory so that he is keeping his most freq[uently used data]” there.
This is the design decision that shaped 6502 programming culture. Zero page is not a convenience, it is the register file the chip does not have, and the scramble for zero-page bytes on machines where the ROM had already claimed most of them is a direct consequence.
Where the cycle comes back
The saving is not uniform, and the manual is honest about it:
there is no time savings of Zero Page indexing over absolute indexing without page crossing … In the case of the Zero Page, there is no opportunity for this type of overlap; therefore, indexed Zero Page instructions take one cycle longer than non-indexed instructions.
An absolute indexed access can fetch the address high byte at the same time as it adds the index to the low byte — two jobs in one cycle. Zero page has no high byte to fetch, so there is nothing to overlap with, and the addition costs a cycle of its own. The mode that saves a cycle in its simple form gives it back when indexed.
The read that goes to the wrong address
The most consequential paragraph is one the summaries never carry. When an indexed access crosses a page boundary, the processor has already put a wrong address on the bus:
In both Zero Page indexed and absolute indexed with a page crossing, there are incorrect addresses calculated. Provisions have been made to make certain that, only a READ operation occurs during this time. Memory modifying operations such as STORE, SHIFT, ROTATE, etc. have all been delayed until the correct address is available, thereby prohibiting any possibility of writing data in an incorrect location and destroying the previous data in that location.
So the spurious access is not a defect. MOS knew the address would be wrong for a cycle, and made the guarantee that it could: nothing is ever written there.
For memory this is invisible — a wasted read costs a cycle and nothing else. For memory-mapped hardware it is anything but, because a read of a hardware register can clear a flag, advance a pointer or acknowledge an interrupt. A 6502 program that indexes across a page boundary near an I/O chip can trigger a side effect at an address it never intended to touch, and an emulator that models only the correct accesses will run that program differently from the machine.
The stack is next door to zero page
The stack’s position is usually given as a fixed fact. The manual gives it as a consequence: page one is where the stack sits because page one is what you reach when page zero runs out — it “would be the next memory location added if the Zero Page operation requirements exceed Page” zero.
The addressing is as simple as it sounds. “The microprocessor always puts out the
address 0100 plus stack register for every stack operation” — an 8-bit stack
pointer with a constant 01 bolted on top, which is why the 6502 stack is 256
bytes and cannot be moved.
Even that was not quite absolute at first: on the earliest parts “the user can either locate the stack in Page Zero or Page One, depending on whether or not Page One exists for his hardware”.
Architecture highlights
- Instruction set: 56 official opcodes with multiple addressing modes each.
- Addressing modes: immediate, absolute, zero-page, indexed, indirect, and combinations.
- No multiplication/division: these must be implemented in software.
- Little-endian: low byte stored first in memory.
- Interrupts: NMI is edge-triggered (vectors via $FFFA-$FFFB), IRQ is level-triggered (vectors via $FFFE-$FFFF, shared with BRK). Reset vectors via $FFFC-$FFFD. All take 7 cycles.
Status register (P)
| Bit | Flag | Meaning |
|---|---|---|
| 7 | N | Negative — copy of result bit 7 |
| 6 | V | Overflow — signed overflow on ADC/SBC |
| 5 | — | Unused (reads as 1 when pushed to stack) |
| 4 | B | Break — no physical bit; appears 1 when pushed by BRK/PHP, 0 when pushed by IRQ/NMI |
| 3 | D | Decimal — selects BCD mode for ADC/SBC (no effect on the NES 2A03) |
| 2 | I | Interrupt disable — when 1, IRQ is masked |
| 1 | Z | Zero — set if result == 0 |
| 0 | C | Carry — unsigned overflow / shift-out / comparison result |
Key addressing modes
| Mode | Syntax | Example | Description |
|---|---|---|---|
| Immediate | #$nn | LDA #$40 | Load literal value |
| Zero-page | $nn | LDA $40 | Fast access to $00-$FF |
| Absolute | $nnnn | LDA $C000 | Full 16-bit address |
| Indexed | $nnnn,X | LDA $C000,X | Address + X register |
| Indirect | ($nnnn) | JMP ($1234) | Jump to address stored at location |
Famous quirks
- JMP indirect page-wrap bug: if the operand of
JMP ($xxFF)lies on a page boundary, the high byte of the target is fetched from$xx00, not$xx100— the high byte wraps within the page. The 65C02 fixes this. - Decimal mode flag behaviour: in BCD mode, the N, V, and Z flags reflect the binary intermediate result, not the BCD output. (Most code re-tests after the operation.)
- Page-cross cycle penalty: read instructions (LDA/CMP/ADC/etc.) using
abs,X/abs,Y/(zp),Ycost +1 cycle if the index crosses a page boundary. Read-modify-write (ASL $nnnn,X) and store (STA $nnnn,X) instructions always take the maximum cycle count — they always do a dummy read at the unfixed address. - Reset state: I=1, D=1 on some early NMOS parts; A/X/Y/SP/PC undefined. Reset code typically begins with
LDX #$FF / TXS / CLDto set up the stack and clear decimal mode.
Undocumented (illegal) opcodes
The NMOS 6502 has 105 unused opcode slots, of which several dozen produce reproducible behaviour and are widely used in production NES and C64 software. Common examples:
| Mnemonic | Effect |
|---|---|
| LAX | Load A and X simultaneously |
| SAX | Store A AND X |
| DCP | Decrement memory, then compare with A |
| ISC | Increment memory, then subtract from A with borrow |
| SLO/RLA/SRE/RRA | Shift/rotate memory, then OR/AND/EOR/ADC with A |
| ANC | AND immediate, then copy bit 7 to carry |
The 65C02 (CMOS) replaces most of these with new documented instructions, so code using illegals breaks on CMOS variants.
Variants and descendants
- 6510: C64’s version with built-in I/O port.
- 6507: stripped-down version for Atari 2600 (13-bit address bus, 8 KB addressable).
- 2A03: NES variant — 6502 core with decimal-mode adder disabled in hardware, integrated APU and DMA controller.
- 65C02: CMOS version with additional instructions and the JMP indirect bug fixed.
- 65816: 16-bit successor used in Apple IIGS and SNES.
Cultural impact
The 6502 created the first generation of assembly programmers. Its constraints—limited registers, no hardware multiply—forced creative solutions that became hallmarks of 8-bit game design. The skills learnt on a 6502 transfer directly to understanding all computer architecture.