6502 Assembly Language with AT28C256 EEPROM

January 20, 2026 ยท View on GitHub

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.


1. Scope and Assumptions

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)

2. AT28C256 EEPROM Overview

ParameterValue
Capacity32 KB (32768 bytes)
Address LinesA0-A14
Data LinesD0-D7
Access Time~150 ns
Supply Voltage5 V
PackageDIP-28 / PLCC

Typical Memory Map Usage

Address RangeUsage
$8000-$FFFFEEPROM (code + vectors)
$FFFA-$FFFFInterrupt vectors

3. 6502 Memory Map Example

\$0000-\$00FF  Zero Page (RAM)
\$0100-\$01FF  Stack
\$0200-\$7FFF  RAM / I/O
\$8000-$FFFF  AT28C256 EEPROM

4. Reset and Interrupt Vectors

The 6502 reads vectors from the top of memory:

VectorAddressDescription
NMI$FFFA-$FFFBNon-maskable interrupt
RESET$FFFC-$FFFDReset entry point
IRQ/BRK$FFFE-$FFFFMaskable interrupt

Vector Definition Example

        .org $FFFA
        .word nmi_handler
        .word reset
        .word irq_handler

5. Assembly Program Structure

Typical Layout

        .org \$8000

reset:
        sei             ; Disable IRQs
        cld             ; Clear decimal mode
        ldx #$FF
        txs             ; Initialize stack

main:
        jmp main

6. Essential 6502 Instructions

Registers

RegisterPurpose
AAccumulator
X, YIndex registers
SPStack pointer
PCProgram counter
PProcessor status

Common Instructions

InstructionFunction
LDA/STALoad/store accumulator
LDX/LDYLoad index registers
JMP/JSRJump / subroutine
RTSReturn from subroutine
BEQ/BNEConditional branch
SEI/CLIDisable/enable IRQ

7. Addressing Modes (Common)

ModeExampleNotes
ImmediateLDA #\$01Constant
Zero PageLDA \$00Fast
AbsoluteLDA \$8000Full address
IndexedLDA \$2000,XTables
IndirectJMP ($FFFC)Vectors

8. Writing Code for EEPROM Execution

Key Considerations

  • Code is read-only at runtime
  • Self-modifying code not recommended
  • Place jump tables and constants in EEPROM
  • Use RAM for variables and stack

Zero Page Variable Example

counter = \$00

        lda #\$00
        sta counter

9. Timing and Performance

  • EEPROM access time must meet CPU clock requirements
  • AT28C256 supports ~1 MHz comfortably
  • Faster clocks may require wait states or ROM shadowing

10. Example: Simple LED Toggle (Memory-Mapped I/O)

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

11. Assembling and Programming Workflow

  1. Write source (.asm)
  2. Assemble to binary
  3. Pad or relocate to $8000
  4. Program AT28C256 via T48 / minipro
  5. Insert EEPROM and reset CPU

12. Assembler Directives (Common)

DirectivePurpose
.orgSet program origin
.byteDefine byte
.wordDefine word (little-endian)
.includeInclude file
.equConstant definition

13. Common Mistakes

IssueResult
Missing vectorsCPU hangs on reset
Wrong .orgCode not executed
Using RAM addresses in ROMCrash
Stack not initializedUndefined behavior


Document Scope: 6502 assembly stored in AT28C256 EEPROM Audience: Retrocomputing, SBC designers, embedded hobbyists Status: Stable reference