This 6502 Cheat Sheet encapsulates the core elements essential for programming with the 6502 microprocessor, covering registers, flags, addressing modes, and a succinct overview of memory layout. It breaks down the instruction set into logical categories like Load/Store operations, Arithmetic, and System Control, enhancing understanding with flag effects for each command. Highlighting illegal opcodes and offering practical tips, this guide is a handy reference for both beginners and experienced programmers, supplemented with useful links for deeper exploration.
Key Concepts
Registers
- A (Accumulator): Used for arithmetic, logic operations, and data transfer.
- X and Y (Index Registers): Used for indexing and loops.
- PC (Program Counter): Points to the next instruction to execute.
- SP (Stack Pointer): Points to the current top of the stack.
- SR (Status Register): Holds FLAGS [NV-BDIZC] that describe the state of the processor. See a detailed description in the following block.
Flags
- N (Negative): Set if the result of the last operation is negative.
- V (Overflow): Set if the last addition or subtraction resulted in an overflow.
- B (Break Command): Set when a software interrupt (BRK instruction) is executed.
- D (Decimal Mode): Set if the processor is in decimal mode.
- I (Interrupt Disable): Set to disable interrupts.
- Z (Zero): Set if the result of the last operation is zero.
- C (Carry): Set if the last operation resulted in a carry out or borrow into the high order bit.
Addressing Modes
- Immediate:
LDA #$FF
- Load immediate value into A. - Zero Page:
LDA $00
- Access memory location on the zero page. - Zero Page,X/Y:
LDX $00,X
- Access memory using zero page address offset by X or Y. - Absolute:
JMP $F000
- Jump to a specific memory address. - Absolute,X/Y:
STA $3000,X
- Store A at an address offset by X or Y. - Indirect:
JMP ($FFFC)
- Jump to the address stored at a specific location. - Indexed Indirect:
LDA ($40,X)
- Use X to find a zero page address which points to the target address. - Indirect Indexed:
LDA ($40),Y
- Use a zero page address to find a base address, then add Y.
Memory Layout
- The 6502's program counter is 16 bits wide, so up to 2^16 (65536) bytes of memory are addressable.
- 16-bit values are stored in memory in little-endian.
- Signed integers can represent values from -128 (%10000000) to +127 (%01111111).
Region | Contents | Description |
---|---|---|
$0000 - $00FF | Zero page | Faster to access than other pages. |
$0100 - $01FF | Stack | Last-in first-out data structure (LIFO). Grows backwards from $01FF to $0100. Used by some transfer, stack, and subroutine instructions |
$0200 - $FFFF | General-purpose | Memory that can be used for whatever purpose needed. Devices that use the 6502 processor may choose to reserve sub-regions for other purposes. |
Instructions
Load/Store Operations
LDA
Load Accumulator with Memory (M → A)LDX
Load X Register with Memory (M → X)LDY
Load Y Register with Memory (M → Y)STA
Store Accumulator in Memory (A → M)STX
Store X Register in Memory (X → M)STY
Store Y Register in Memory (Y → M)
Instr. | N | V | - | B | D | I | Z | C |
---|---|---|---|---|---|---|---|---|
LDA | ✓ | - | - | - | - | - | ✓ | - |
LDX | ✓ | - | - | - | - | - | ✓ | - |
LDY | ✓ | - | - | - | - | - | ✓ | - |
STA | - | - | - | - | - | - | - | - |
STX | - | - | - | - | - | - | - | - |
STY | - | - | - | - | - | - | - | - |
Transfer
TAX
Transfer Accumulator To X (A → X)TAY
Transfer Accumulator To Y (A → Y)TSX
Transfer Stack Pointer To X (S → X)TXA
Transfer X to Accumulator (X → A)TYA
Transfer Y to Accumulator (Y → A)TXS
Transfer X to Stack Pointer (A → X)
Instr. | N | V | - | B | D | I | Z | C |
---|---|---|---|---|---|---|---|---|
TAX | ✓ | - | - | - | - | - | ✓ | - |
TAY | ✓ | - | - | - | - | - | ✓ | - |
TSX | ✓ | - | - | - | - | - | ✓ | - |
TXA | ✓ | - | - | - | - | - | ✓ | - |
TYA | ✓ | - | - | - | - | - | ✓ | - |
TXS | - | - | - | - | - | - | - | - |
Stack
PHA
Push Accumulator On Stack (A↓)PHP
Push Processor Status On Stack (P↓)PLA
Pull Accumulator From Stack (A↑)PLP
Pull Processor Status From Stack (P↑)
Instr. | N | V | - | B | D | I | Z | C |
---|---|---|---|---|---|---|---|---|
PHA | - | - | - | - | - | - | - | - |
PHP | - | - | - | - | - | - | - | - |
PLA | ✓ | - | - | - | - | - | ✓ | - |
PLP | ✓ | ✓ | - | - | ✓ | ✓ | ✓ | ✓ |
Arithmetic
ADC
Add Memory to Accumulator with Carry (A+M+C → A, C)SBC
Subtract Memory from Accumulator with Borrow* (A-M -~C → A)
Instr. | N | V | - | B | D | I | Z | C |
---|---|---|---|---|---|---|---|---|
ADC | ✓ | ✓ | - | - | - | - | ✓ | ✓ |
SBC | ✓ | ✓ | - | - | - | - | ✓ | ✓ |
- Borrow is defined as the carry flag complemented.
Increment/Decrement
INC
Increment Memory by 1 (M+1 → M)INX
Increment X Register by 1 (X+1 → X)INY
Increment Y Register by 1 (Y+1 → Y)DEC
Decrement Memory by 1 (M-1 → M)DEX
Decrement X Register by 1 (X-1 → X)DEY
Decrement Y Register by 1 (Y-1 → Y)
Instr. | N | V | - | B | D | I | Z | C |
---|---|---|---|---|---|---|---|---|
INC | ✓ | - | - | - | - | - | ✓ | - |
INX | ✓ | - | - | - | - | - | ✓ | - |
INY | ✓ | - | - | - | - | - | ✓ | - |
DEC | ✓ | - | - | - | - | - | ✓ | - |
DEX | ✓ | - | - | - | - | - | ✓ | - |
DEY | ✓ | - | - | - | - | - | ✓ | - |
Shifts and Rotations
ASL
Arithmetic Shift Left (C←[M7...M0]←0)LSR
Logical Shift Right (0→[M7...M0]→C)ROL
Rotate Left (C←[M7...M0]←C)ROR
Rotate Right (C→[M7...M0]→C)
Instr. | N | V | - | B | D | I | Z | C |
---|---|---|---|---|---|---|---|---|
ASL | ✓ | - | - | - | - | - | ✓ | ✓ |
LSR | 0 | - | - | - | - | - | ✓ | ✓ |
ROL | ✓ | - | - | - | - | - | ✓ | ✓ |
ROR | ✓ | - | - | - | - | - | ✓ | ✓ |
Logical
AND
AND Memory with Accumulator (A ∧ M → A)ORA
OR Memory with Accumulator (A ∨ M → A)EOR
Exclusive OR Memory with Accumulator (A ⊻ M → A)BIT
Test Bits in Memory with Accumulator (A ∧ M, M7→N, M6 → V)
Instr. | N | V | - | B | D | I | Z | C |
---|---|---|---|---|---|---|---|---|
AND | ✓ | - | - | - | - | - | ✓ | - |
ORA | ✓ | - | - | - | - | - | ✓ | - |
EOR | ✓ | - | - | - | - | - | ✓ | - |
BIT | ✓ | ✓ | - | - | - | - | ✓ | - |
Compare
CMP
Compare Memory and AccumulatorCPX
Compare Memory and Index XCPY
Compare Memory and Index Y
Compare Result | N | Z | C |
---|---|---|---|
A, X, or Y < Memory | * | 0 | 0 |
A, X, or Y = Memory | 0 | 1 | 1 |
A, X, or Y > Memory | * | 0 | 1 |
Branching
BCC
Branch on Carry Clear (C = 0)BCS
Branch on Carry Set (C = 1)BEQ
Branch on Result Zero (Z = 1)BMI
Branch on Result Minus (N = 1)BNE
Branch on Result not Zero (Z = 0)BPL
Branch on Result Plus (N = 0)BVC
Branch on Overflow Clear (V = 0)BVS
Branch on Overflow Set (V = 1)
Flags
CLC
Clear Carry Flag (0 → C)CLD
Clear Decimal Mode (0 → D)CLI
Clear Interrupt Disable (0 → I)CLV
Clear Overflow Flag (0 → V)SEC
Set Carry Flag (1 → C)SED
Set Decimal Mode (1 → D)SEI
Set Interrupt Disable (1 → I)NOP
No Operation
Instr. | N | V | - | B | D | I | Z | C |
---|---|---|---|---|---|---|---|---|
CLC | - | - | - | - | - | - | - | 0 |
CLD | - | - | - | - | 0 | - | - | - |
CLI | - | - | - | - | - | 0 | - | - |
CLV | - | 0 | - | - | - | - | - | - |
SEC | - | - | - | - | - | - | - | 1 |
SED | - | - | - | - | 1 | - | - | - |
SEI | - | - | - | - | - | 1 | - | - |
NOP | - | - | - | - | - | - | - | - |
System Control
BRK
Force Break (PC + 2↓)JMP
Jump to New Location ([PC + 1]→PCL, [PC + 2]→PCH)JSR
Jump to Subroutine (PC + 2↓)RTI
Return from Interrupt (P↑ PC↑)RTS
Return from Subroutine (PC↑, PC + 1→PC)NOP
No Operation
Instr. | N | V | - | B | D | I | Z | C |
---|---|---|---|---|---|---|---|---|
BRK | - | - | - | - | - | 1 | - | - |
JMP | - | - | - | - | - | - | - | - |
JSR | - | - | - | - | - | - | - | - |
RTI | ✓ | ✓ | - | - | ✓ | ✓ | ✓ | ✓ |
RTS | - | - | - | - | - | - | - | - |
NOP | - | - | - | - | - | - | - | - |
Illegal opcodes
ALR
AND + LSR (A AND oper, 0 → [M7...M0] → C)ANC
AND + set C as ASL (A AND oper, bit(7) → C)ANC
(ANC2) AND oper + set C as ROL (A AND oper, bit(7) → C)ANE
(XAA) AND X + AND oper (unsatble)ARR
AND oper + ROR (A AND oper, C → [M7...M0] → C)DCP
(DCM) DEC oper + CMP oper (M - 1 → M, A - M)ISC
(ISB, INS) INC oper + SBC oper (M + 1 → M, A - M - C → A)LAS
(LAR) LDA/TSX oper (M AND SP → A, X, SP)LAX
LDA oper + LDX oper (M → A → X)LXA
Store * AND oper in A and X (highly unstable)RLA
ROL oper + AND oper (M = C ← [M7...M0] ← C, A AND M → A)RRA
ROR oper + ADC oper (M = C → [M7...M0] → C, A + M + C → A, C)SAX
(AXS, AAX) A AND X → MSBX
(AXS, SAX) (A AND X) - oper → XSHA
(AHX, AXA) A AND X AND (H+1) → MSHX
(A11, SXA, XAS) Stores X AND (high-byte of addr. + 1) at addr.SHY
(A11, SYA, SAY) Stores Y AND (high-byte of addr. + 1) at addr.SLO
(ASO) ASL oper + ORA operSRE
(LSE) LSR oper + EOR operTAS
(XAS, SHS) Puts A AND X in SP and stores A AND X AND (high-byte of addr. + 1) at addr.USBC
(SBC) SBC oper + NOP (A - M - C → A)JAM
(KIL, HLT) Freezes the CPU.- 6502 Illegal opcodes
Basic Code Snippets
Subroutine Call and Return
JSR mySubroutine
; Call subroutine
; Code continues here after subroutine returns
JMP endProgram
;Jump to the end of the program or other operations
mySubroutine:
;Subroutine operations here
RTS
;Return from subroutine
endProgram:
; Program end or halt
Delay Loop
`LDX #$FF` ; Outer loop counter
outerLoop:
`LDY #$FF` ; Inner loop counter
innerLoop:
`DEY` ; Decrement Y
`BNE innerLoop ` ; Continue inner loop until Y=0
`DEX` ; Decrement X
`BNE outerLoop` ; Continue outer loop until X=0
; Delay complete
Useful Tips
General Tips
- Use comments to make your code understandable.
- Remember to set and clear the decimal mode (D flag) as needed.
- Use stack operations (
PHA
,PLA
, etc.) to save and restore registers during subroutine calls. - Keep track of the zero page for quick and efficient data access.
- Utilize loops and conditional branches effectively to control program flow.