A practical specification for writing 6502/65C02 assembly language programs intended to be stored in and executed from an AT28C256 (32 KB) parallel EEPROM in single-board computers (SBCs) and retro systems.
This document assumes:
- A 6502-family CPU (6502, 65C02, or compatible)
- Program code stored in an AT28C256 (32K x 8) EEPROM
- Memory-mapped I/O (e.g., 6522 VIA)
- Reset and interrupt vectors located in EEPROM
- External RAM mapped elsewhere (e.g., 62256 SRAM)
| Parameter | Value |
|---|
| Capacity | 32 KB (32768 bytes) |
| Address Lines | A0-A14 |
| Data Lines | D0-D7 |
| Access Time | ~150 ns |
| Supply Voltage | 5 V |
| Package | DIP-28 / PLCC |
| Address Range | Usage |
|---|
$8000-$FFFF | EEPROM (code + vectors) |
$FFFA-$FFFF | Interrupt vectors |
\$0000-\$00FF Zero Page (RAM)
\$0100-\$01FF Stack
\$0200-\$7FFF RAM / I/O
\$8000-$FFFF AT28C256 EEPROM
The 6502 reads vectors from the top of memory:
| Vector | Address | Description |
|---|
| NMI | $FFFA-$FFFB | Non-maskable interrupt |
| RESET | $FFFC-$FFFD | Reset entry point |
| IRQ/BRK | $FFFE-$FFFF | Maskable interrupt |
.org $FFFA
.word nmi_handler
.word reset
.word irq_handler
.org \$8000
reset:
sei ; Disable IRQs
cld ; Clear decimal mode
ldx #$FF
txs ; Initialize stack
main:
jmp main
| Register | Purpose |
|---|
| A | Accumulator |
| X, Y | Index registers |
| SP | Stack pointer |
| PC | Program counter |
| P | Processor status |
| Instruction | Function |
|---|
| LDA/STA | Load/store accumulator |
| LDX/LDY | Load index registers |
| JMP/JSR | Jump / subroutine |
| RTS | Return from subroutine |
| BEQ/BNE | Conditional branch |
| SEI/CLI | Disable/enable IRQ |
| Mode | Example | Notes |
|---|
| Immediate | LDA #\$01 | Constant |
| Zero Page | LDA \$00 | Fast |
| Absolute | LDA \$8000 | Full address |
| Indexed | LDA \$2000,X | Tables |
| Indirect | JMP ($FFFC) | Vectors |
- Code is read-only at runtime
- Self-modifying code not recommended
- Place jump tables and constants in EEPROM
- Use RAM for variables and stack
counter = \$00
lda #\$00
sta counter
- EEPROM access time must meet CPU clock requirements
- AT28C256 supports ~1 MHz comfortably
- Faster clocks may require wait states or ROM shadowing
PORTB = \$6000
DDRB = \$6002
.org \$8000
reset:
sei
ldx #$FF
txs
lda #$FF
sta DDRB
loop:
lda #$FF
sta PORTB
jsr delay
lda #\$00
sta PORTB
jsr delay
jmp loop
- Write source (
.asm)
- Assemble to binary
- Pad or relocate to
$8000
- Program AT28C256 via T48 / minipro
- Insert EEPROM and reset CPU
| Directive | Purpose |
|---|
.org | Set program origin |
.byte | Define byte |
.word | Define word (little-endian) |
.include | Include file |
.equ | Constant definition |
| Issue | Result |
|---|
| Missing vectors | CPU hangs on reset |
Wrong .org | Code not executed |
| Using RAM addresses in ROM | Crash |
| Stack not initialized | Undefined behavior |
Document Scope: 6502 assembly stored in AT28C256 EEPROM
Audience: Retrocomputing, SBC designers, embedded hobbyists
Status: Stable reference