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
LDALoad Accumulator with Memory (M → A)LDXLoad X Register with Memory (M → X)LDYLoad Y Register with Memory (M → Y)STAStore Accumulator in Memory (A → M)STXStore X Register in Memory (X → M)STYStore Y Register in Memory (Y → M)
| Instr. | N | V | - | B | D | I | Z | C |
|---|---|---|---|---|---|---|---|---|
| LDA | ✓ | - | - | - | - | - | ✓ | - |
| LDX | ✓ | - | - | - | - | - | ✓ | - |
| LDY | ✓ | - | - | - | - | - | ✓ | - |
| STA | - | - | - | - | - | - | - | - |
| STX | - | - | - | - | - | - | - | - |
| STY | - | - | - | - | - | - | - | - |
Transfer
TAXTransfer Accumulator To X (A → X)TAYTransfer Accumulator To Y (A → Y)TSXTransfer Stack Pointer To X (S → X)TXATransfer X to Accumulator (X → A)TYATransfer Y to Accumulator (Y → A)TXSTransfer X to Stack Pointer (A → X)
| Instr. | N | V | - | B | D | I | Z | C |
|---|---|---|---|---|---|---|---|---|
| TAX | ✓ | - | - | - | - | - | ✓ | - |
| TAY | ✓ | - | - | - | - | - | ✓ | - |
| TSX | ✓ | - | - | - | - | - | ✓ | - |
| TXA | ✓ | - | - | - | - | - | ✓ | - |
| TYA | ✓ | - | - | - | - | - | ✓ | - |
| TXS | - | - | - | - | - | - | - | - |
Stack
PHAPush Accumulator On Stack (A↓)PHPPush Processor Status On Stack (P↓)PLAPull Accumulator From Stack (A↑)PLPPull Processor Status From Stack (P↑)
| Instr. | N | V | - | B | D | I | Z | C |
|---|---|---|---|---|---|---|---|---|
| PHA | - | - | - | - | - | - | - | - |
| PHP | - | - | - | - | - | - | - | - |
| PLA | ✓ | - | - | - | - | - | ✓ | - |
| PLP | ✓ | ✓ | - | - | ✓ | ✓ | ✓ | ✓ |
Arithmetic
ADCAdd Memory to Accumulator with Carry (A+M+C → A, C)SBCSubtract 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
INCIncrement Memory by 1 (M+1 → M)INXIncrement X Register by 1 (X+1 → X)INYIncrement Y Register by 1 (Y+1 → Y)DECDecrement Memory by 1 (M-1 → M)DEXDecrement X Register by 1 (X-1 → X)DEYDecrement Y Register by 1 (Y-1 → Y)
| Instr. | N | V | - | B | D | I | Z | C |
|---|---|---|---|---|---|---|---|---|
| INC | ✓ | - | - | - | - | - | ✓ | - |
| INX | ✓ | - | - | - | - | - | ✓ | - |
| INY | ✓ | - | - | - | - | - | ✓ | - |
| DEC | ✓ | - | - | - | - | - | ✓ | - |
| DEX | ✓ | - | - | - | - | - | ✓ | - |
| DEY | ✓ | - | - | - | - | - | ✓ | - |
Shifts and Rotations
ASLArithmetic Shift Left (C←[M7...M0]←0)LSRLogical Shift Right (0→[M7...M0]→C)ROLRotate Left (C←[M7...M0]←C)RORRotate Right (C→[M7...M0]→C)
| Instr. | N | V | - | B | D | I | Z | C |
|---|---|---|---|---|---|---|---|---|
| ASL | ✓ | - | - | - | - | - | ✓ | ✓ |
| LSR | 0 | - | - | - | - | - | ✓ | ✓ |
| ROL | ✓ | - | - | - | - | - | ✓ | ✓ |
| ROR | ✓ | - | - | - | - | - | ✓ | ✓ |
Logical
ANDAND Memory with Accumulator (A ∧ M → A)ORAOR Memory with Accumulator (A ∨ M → A)EORExclusive OR Memory with Accumulator (A ⊻ M → A)BITTest Bits in Memory with Accumulator (A ∧ M, M7→N, M6 → V)
| Instr. | N | V | - | B | D | I | Z | C |
|---|---|---|---|---|---|---|---|---|
| AND | ✓ | - | - | - | - | - | ✓ | - |
| ORA | ✓ | - | - | - | - | - | ✓ | - |
| EOR | ✓ | - | - | - | - | - | ✓ | - |
| BIT | ✓ | ✓ | - | - | - | - | ✓ | - |
Compare
CMPCompare Memory and AccumulatorCPXCompare Memory and Index XCPYCompare 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
BCCBranch on Carry Clear (C = 0)BCSBranch on Carry Set (C = 1)BEQBranch on Result Zero (Z = 1)BMIBranch on Result Minus (N = 1)BNEBranch on Result not Zero (Z = 0)BPLBranch on Result Plus (N = 0)BVCBranch on Overflow Clear (V = 0)BVSBranch on Overflow Set (V = 1)
Flags
CLCClear Carry Flag (0 → C)CLDClear Decimal Mode (0 → D)CLIClear Interrupt Disable (0 → I)CLVClear Overflow Flag (0 → V)SECSet Carry Flag (1 → C)SEDSet Decimal Mode (1 → D)SEISet Interrupt Disable (1 → I)NOPNo 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
BRKForce Break (PC + 2↓)JMPJump to New Location ([PC + 1]→PCL, [PC + 2]→PCH)JSRJump to Subroutine (PC + 2↓)RTIReturn from Interrupt (P↑ PC↑)RTSReturn from Subroutine (PC↑, PC + 1→PC)NOPNo Operation
| Instr. | N | V | - | B | D | I | Z | C |
|---|---|---|---|---|---|---|---|---|
| BRK | - | - | - | - | - | 1 | - | - |
| JMP | - | - | - | - | - | - | - | - |
| JSR | - | - | - | - | - | - | - | - |
| RTI | ✓ | ✓ | - | - | ✓ | ✓ | ✓ | ✓ |
| RTS | - | - | - | - | - | - | - | - |
| NOP | - | - | - | - | - | - | - | - |
Illegal opcodes
ALRAND + LSR (A AND oper, 0 → [M7...M0] → C)ANCAND + 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)ARRAND 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)LAXLDA oper + LDX oper (M → A → X)LXAStore * AND oper in A and X (highly unstable)RLAROL oper + AND oper (M = C ← [M7...M0] ← C, A AND M → A)RRAROR 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 counterouterLoop:
`LDY #$FF` ; Inner loop counterinnerLoop:
`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.
