Post

6502 Assembly Guide

6502 Assembly Programming Guide

This guide covers the fundamentals of programming the 6502 CPU, commonly found in the NES, Commodore 64, Apple II, and other retro hardware. It includes information on registers, flags, memory addressing, arithmetic, comparisons, branching, subroutines, labels, and more.


Registers

RegisterDescription
AAccumulator — for arithmetic, logic, and data transfer.
XIndex register — for loops, offsets, and memory indexing.
YIndex register — similar to X, with some different addressing modes.
SPStack Pointer — points to stack in page $0100.
PCProgram Counter — current instruction location.
PProcessor Status — 8-bit flag register (see below).

Status Flags (Processor Status Register)

FlagBitNameMeaning
N7NegativeSet if bit 7 of the result is 1 (signed negative).
V6OverflowSet if signed overflow occurs.
5(Unused)Always set to 1.
B4BreakSet when BRK instruction runs.
D3DecimalNot used on NES. (Decimal mode.)
I2InterruptDisable (1) or enable (0) IRQ.
Z1ZeroSet if result is zero.
C0CarrySet if carry/borrow occurs in math.
Layout

Memory Addressing Modes

ModeExampleDescription
ImmediateLDA #$10Load constant value $10.
Zero PageLDA $00Access memory in page 0 ($0000-$00FF).
Zero Page,XLDA $00,XZero page plus X offset.
AbsoluteLDA $1234Load from full 16-bit address.
Absolute,XLDA $1234,XAddress + X offset.
Absolute,YLDA $1234,YAddress + Y offset.
IndirectJMP ($1234)Jump to address stored at $1234/$1235.
Indexed Indirect (X)LDA ($20,X)Pointer = $20 + X, then fetch.
Indirect Indexed (Y)LDA ($20),YFetch pointer from $20, then add Y.
RelativeBEQ LabelBranch relative to PC (for conditionals).

Arithmetic and Logic

Load and Store

LDA #$10     ; Load 16 into A
LDX #$00     ; Load 0 into X
LDY $00      ; Load value from memory $00 into Y
STA $0200    ; Store A into memory address $0200

Math

LDA #$05     ; A = 5
ADC #$03     ; A = A + 3 + Carry (use CLC beforehand if needed)

SEC          ; Set carry for subtraction
LDA #$08     ; A = 8
SBC #$02     ; A = A - 2 - (1 - Carry) = 6

Increment/Decrement

INX          ; X = X + 1
INY          ; Y = Y + 1
DEX          ; X = X - 1
DEY          ; Y = Y - 1

Bitwise Logic

LDA #%10101010 ; A = 170
AND #%11001100 ; A = A AND 204 → Result is #%10001000

ORA #%00001111 ; A = A OR 15

EOR #%11111111 ; A = A XOR 255 (bit flip)

Comparisons and Branching

Compare Registers

LDA #$05
CMP #$05     ; Compare A with 5 → Sets Z flag if equal

LDX #$03
CPX #$04     ; Compare X with 4

LDY #$08
CPY #$07     ; Compare Y with 7

Branch Instructions

InstructionDescription
BEQBranch if Equal (Z=1)
BNEBranch if Not Equal (Z=0)
BCSBranch if Carry Set (C=1)
BCCBranch if Carry Clear (C=0)
BMIBranch if Minus (N=1)
BPLBranch if Positive (N=0)
BVSBranch if Overflow Set (V=1)
BVCBranch if Overflow Clear (V=0)

Example Loop:

LDX #$05      ; X = 5

Loop:
    DEX        ; X = X - 1
    BNE Loop   ; If X ≠ 0, loop back

Subroutines and Labels

Define Labels:

Start:
    LDA #$01
    STA $0200
    JMP Start  ; Infinite loop

Subroutines:

JSR MySub     ; Jump to subroutine

; ...do other stuff...

MySub:
    LDA #$FF
    STA $00
    RTS        ; Return from subroutine

Stack Operations

InstructionDescription
PHAPush A onto stack
PLAPull A from stack
PHPPush Processor Status
PLPPull Processor Status
JSRJump to subroutine (Push return address)
RTSReturn from subroutine
BRKForce interrupt (Push PC+2 and status)
RTIReturn from interrupt

Example: Save and Restore Registers

    PHA         ; Save A
    TXA
    PHA         ; Save X
    TYA
    PHA         ; Save Y

    ; Subroutine logic here

    PLA         ; Restore Y
    TAY
    PLA         ; Restore X
    TAX
    PLA         ; Restore A
    RTS

Miscellaneous Instructions

  • NOP — No operation (does nothing; placeholder).
  • CLC / SEC — Clear/Set Carry flag.
  • CLD / SED — Clear/Set Decimal flag (not used on NES).
  • CLI / SEI — Clear/Set Interrupt Disable.
  • CLV — Clear Overflow flag.

Example Program: Fill Memory with a Value

LDX #$00          ; Start index at 0
LDA #$FF          ; Value to write

Loop:
    STA $0200,X   ; Store value at $0200 + X
    INX           ; Increment index
    CPX #$10      ; Compare X to 16
    BNE Loop      ; If X ≠ 16, continue looping

BRK                ; End (break)

Resources

Layout

6502 Instruction Set Guide (.pdf): https://forums.atariage.com/applications/core/interface/file/attachment.php?id=888275

This post is licensed under CC BY 4.0 by the author.