6502 opcodes for hackers
6502 Opcodes for Hackers is a reference guide for experienced programmers. It focuses on the practical application of both standard and stable non-standard NMOS 6502 opcodes, including common tricks and non-obvious behaviors. It intentionally omits highly unstable opcodes to provide a focused, practical resource.
Contents
- 1 Opcode Matrix
- 2 Standard Opcodes
- 2.1 ADC (ADd with Carry)
- 2.2 AND (bitwise AND with accumulator)
- 2.3 ASL (Arithmetic Shift Left)
- 2.4 Branch Instructions
- 2.5 BIT (test BITS)
- 2.6 BRK (BReaK)
- 2.7 Compare Instructions
- 2.8 Decrement & Increment Instructions
- 2.9 EOR (bitwise Exclusive OR)
- 2.10 Flag Instructions
- 2.11 JMP (JuMP)
- 2.12 JSR (Jump to SubRoutine)
- 2.13 Load Instructions
- 2.14 LSR (Logical Shift Right)
- 2.15 NOP (No OPeration)
- 2.16 ORA (bitwise OR with Accumulator)
- 2.17 Register Instructions
- 2.18 ROL (ROtate Left)
- 2.19 ROR (ROtate Right)
- 2.20 RTI (ReTurn from Interrupt)
- 2.21 RTS (ReTurn from Subroutine)
- 2.22 SBC (SuBtract with Carry)
- 2.23 Stack Instructions
- 2.24 Store Instructions
- 3 Stable & Semi-Stable Illegal Opcodes
- 4 Attribution
Opcode Matrix
This table provides a complete overview of the NMOS 6502 opcode map. Each mnemonic links to its detailed description below.
Legend:
- Blue: Standard Opcodes
- Green: Stable Illegal Opcodes
- Yellow: Semi-Stable Illegal Opcodes (use with caution)
- Red: Unstable/Unreliable Opcodes (details not included below)
Standard Opcodes
This section covers the official, documented NMOS 6502 opcodes.
ADC (ADd with Carry)
Adds memory and the Carry flag to the accumulator. To perform an 8-bit addition, a preceding `CLC` is required. The `V` flag detects signed overflow, and the `D` flag enables BCD arithmetic. Affects Flags: N, V, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | ADC #$44 | $69 | 2 | 2 |
Zero Page | ADC $44 | $65 | 2 | 3 |
Zero Page,X | ADC $44,X | $75 | 2 | 4 |
Absolute | ADC $4400 | $6D | 3 | 4 |
Absolute,X | ADC $4400,X | $7D | 3 | 4+ |
Absolute,Y | ADC $4400,Y | $79 | 3 | 4+ |
Indirect,X | ADC ($44,X) | $61 | 2 | 6 |
Indirect,Y | ADC ($44),Y | $71 | 2 | 5+ |
AND (bitwise AND with accumulator)
Performs a bitwise AND between the accumulator and a memory value. Primarily used to mask (clear) bits. Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | AND #$44 | $29 | 2 | 2 |
Zero Page | AND $44 | $25 | 2 | 3 |
Zero Page,X | AND $44,X | $35 | 2 | 4 |
Absolute | AND $4400 | $2D | 3 | 4 |
Absolute,X | AND $4400,X | $3D | 3 | 4+ |
Absolute,Y | AND $4400,Y | $39 | 3 | 4+ |
Indirect,X | AND ($44,X) | $21 | 2 | 6 |
Indirect,Y | AND ($44),Y | $31 | 2 | 5+ |
ASL (Arithmetic Shift Left)
Shifts an operand left by one bit. Bit 0 is cleared to 0, and the old bit 7 is shifted into the Carry flag. Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Accumulator | ASL A | $0A | 1 | 2 |
Zero Page | ASL $44 | $06 | 2 | 5 |
Zero Page,X | ASL $44,X | $16 | 2 | 6 |
Absolute | ASL $4400 | $0E | 3 | 6 |
Absolute,X | ASL $4400,X | $1E | 3 | 7 |
Branch Instructions
Branch instructions alter program flow based on the state of a specific flag. All use relative addressing, taking a signed 8-bit offset. A branch costs 2 cycles if not taken, 3 if taken within the same page, and 4 if the destination crosses a page boundary. To create an unconditional branch (`BRA`), branch on a flag with a known state. The `V` flag is a good candidate, as it is unaffected by most operations: `CLV` followed by `BVC` will always branch. Affects Flags: none
Mnemonic | Name | HEX |
---|---|---|
BCC | Branch on Carry Clear (C=0) | $90 |
BCS | Branch on Carry Set (C=1) | $B0 |
BEQ | Branch on EQual (Z=1) | $F0 |
BNE | Branch on Not Equal (Z=0) | $D0 |
BMI | Branch on MInus (N=1) | $30 |
BPL | Branch on PLus (N=0) | $10 |
BVC | Branch on oVerflow Clear (V=0) | $50 |
BVS | Branch on oVerflow Set (V=1) | $70 |
BIT (test BITS)
Performs a non-destructive `AND` between the accumulator and memory to set the Z flag, without altering any registers. It also copies bit 7 and bit 6 of the memory operand directly to the N and V flags, respectively. This makes it an essential tool for polling I/O registers. Affects Flags: N, V, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | BIT $44 | $24 | 2 | 3 |
Absolute | BIT $4400 | $2C | 3 | 4 |
BRK (BReaK)
Forces a software interrupt. It pushes PC+2 and the processor status (with the B flag set) to the stack, then jumps via the IRQ vector ($FFFE). An `RTI` returns to the address of `BRK + 2`, allowing it to replace a 2-byte instruction for debugging purposes. Affects Flags: B
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Implied | BRK | $00 | 1 | 7 |
Compare Instructions
These instructions perform a non-destructive subtraction (`Register - Memory`) to set the N, Z, and C flags. They are fundamental for conditional logic and comparisons.
- C flag: Set if `Register >= Memory` (no borrow).
- Z flag: Set if `Register == Memory`.
- N flag: Set to bit 7 of the subtraction result.
CMP (CoMPare accumulator)
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | CMP #$44 | $C9 | 2 | 2 |
Zero Page | CMP $44 | $C5 | 2 | 3 |
Zero Page,X | CMP $44,X | $D5 | 2 | 4 |
Absolute | CMP $4400 | $CD | 3 | 4 |
Absolute,X | CMP $4400,X | $DD | 3 | 4+ |
Absolute,Y | CMP $4400,Y | $D9 | 3 | 4+ |
Indirect,X | CMP ($44,X) | $C1 | 2 | 6 |
Indirect,Y | CMP ($44),Y | $D1 | 2 | 5+ |
CPX (ComPare X register)
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | CPX #$44 | $E0 | 2 | 2 |
Zero Page | CPX $44 | $E4 | 2 | 3 |
Absolute | CPX $4400 | $EC | 3 | 4 |
CPY (ComPare Y register)
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | CPY #$44 | $C0 | 2 | 2 |
Zero Page | CPY $44 | $C4 | 2 | 3 |
Absolute | CPY $4400 | $CC | 3 | 4 |
Decrement & Increment Instructions
These modify a register or memory location by one. Register operations are 1-byte, 2-cycle instructions. Memory operations are read-modify-write and take longer.
DEC (DECrement memory)
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | DEC $44 | $C6 | 2 | 5 |
Zero Page,X | DEC $44,X | $D6 | 2 | 6 |
Absolute | DEC $4400 | $CE | 3 | 6 |
Absolute,X | DEC $4400,X | $DE | 3 | 7 |
DEX (DEcrement X register)
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Implied | DEX | $CA | 1 | 2 |
DEY (DEcrement Y register)
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Implied | DEY | $88 | 1 | 2 |
INC (INCrement memory)
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | INC $44 | $E6 | 2 | 5 |
Zero Page,X | INC $44,X | $F6 | 2 | 6 |
Absolute | INC $4400 | $EE | 3 | 6 |
Absolute,X | INC $4400,X | $FE | 3 | 7 |
INX (INcrement X register)
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Implied | INX | $E8 | 1 | 2 |
INY (INcrement Y register)
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Implied | INY | $C8 | 1 | 2 |
EOR (bitwise Exclusive OR)
Performs a bitwise XOR between the accumulator and memory. Useful for flipping specific bits or for simple checksum calculations. Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | EOR #$44 | $49 | 2 | 2 |
Zero Page | EOR $44 | $45 | 2 | 3 |
Zero Page,X | EOR $44,X | $55 | 2 | 4 |
Absolute | EOR $4400 | $4D | 3 | 4 |
Absolute,X | EOR $4400,X | $5D | 3 | 4+ |
Absolute,Y | EOR $4400,Y | $59 | 3 | 4+ |
Indirect,X | EOR ($44,X) | $41 | 2 | 6 |
Indirect,Y | EOR ($44),Y | $51 | 2 | 5+ |
Flag Instructions
These single-byte, 2-cycle instructions directly manipulate the processor status flags. It is critical to use `CLD` on startup, as the power-on state of the D flag is undefined. Affects Flags: as noted
Mnemonic | Function | HEX |
---|---|---|
CLC | C = 0 | $18 |
SEC | C = 1 | $38 |
CLD | D = 0 | $D8 |
SED | D = 1 | $F8 |
CLI | I = 0 (Enable IRQs) | $58 |
SEI | I = 1 (Disable IRQs) | $78 |
CLV | V = 0 | $B8 |
JMP (JuMP)
Unconditionally transfers program control to a new location. The indirect mode has an infamous hardware bug: if the low byte of the indirect vector is $FF (e.g., `JMP ($30FF)`), the high byte of the jump address is fetched from `$3000`, not `$3100`. Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Absolute | JMP $5597 | $4C | 3 | 3 |
Indirect | JMP ($5597) | $6C | 3 | 5 |
JSR (Jump to SubRoutine)
Pushes the return address (the address of the last byte of the `JSR` instruction) onto the stack and jumps to a new location. Paired with `RTS` for standard subroutine calls. Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Absolute | JSR $5597 | $20 | 3 | 6 |
Load Instructions
Load instructions copy a byte from memory into a register, setting the N and Z flags based on the value loaded. Note the addressing mode asymmetries: `LDX` has a `Zero Page,Y` mode while `LDY` has an `Absolute,X` mode, but not vice-versa.
LDA (LoaD Accumulator)
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | LDA #$44 | $A9 | 2 | 2 |
Zero Page | LDA $44 | $A5 | 2 | 3 |
Zero Page,X | LDA $44,X | $B5 | 2 | 4 |
Absolute | LDA $4400 | $AD | 3 | 4 |
Absolute,X | LDA $4400,X | $BD | 3 | 4+ |
Absolute,Y | LDA $4400,Y | $B9 | 3 | 4+ |
Indirect,X | LDA ($44,X) | $A1 | 2 | 6 |
Indirect,Y | LDA ($44),Y | $B1 | 2 | 5+ |
LDX (LoaD X register)
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | LDX #$44 | $A2 | 2 | 2 |
Zero Page | LDX $44 | $A6 | 2 | 3 |
Zero Page,Y | LDX $44,Y | $B6 | 2 | 4 |
Absolute | LDX $4400 | $AE | 3 | 4 |
Absolute,Y | LDX $4400,Y | $BE | 3 | 4+ |
LDY (LoaD Y register)
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | LDY #$44 | $A0 | 2 | 2 |
Zero Page | LDY $44 | $A4 | 2 | 3 |
Zero Page,X | LDY $44,X | $B4 | 2 | 4 |
Absolute | LDY $4400 | $AC | 3 | 4 |
Absolute,X | LDY $4400,X | $BC | 3 | 4+ |
LSR (Logical Shift Right)
Shifts an operand right by one bit. Bit 7 is cleared to 0, and the old bit 0 is shifted into the Carry flag. Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Accumulator | LSR A | $4A | 1 | 2 |
Zero Page | LSR $44 | $46 | 2 | 5 |
Zero Page,X | LSR $44,X | $56 | 2 | 6 |
Absolute | LSR $4400 | $4E | 3 | 6 |
Absolute,X | LSR $4400,X | $5E | 3 | 7 |
NOP (No OPeration)
The official NOP wastes 2 cycles and does nothing else. Many illegal opcodes also function as NOPs with different cycle and byte counts; some still perform memory reads, which can be useful for I/O timing or acknowledging interrupts without altering registers. Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Implied | NOP | $EA | 1 | 2 |
ORA (bitwise OR with Accumulator)
Performs a bitwise OR between the accumulator and a memory value. Primarily used to set bits. Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | ORA #$44 | $09 | 2 | 2 |
Zero Page | ORA $44 | $05 | 2 | 3 |
Zero Page,X | ORA $44,X | $15 | 2 | 4 |
Absolute | ORA $4400 | $0D | 3 | 4 |
Absolute,X | ORA $4400,X | $1D | 3 | 4+ |
Absolute,Y | ORA $4400,Y | $19 | 3 | 4+ |
Indirect,X | ORA ($44,X) | $01 | 2 | 6 |
Indirect,Y | ORA ($44),Y | $11 | 2 | 5+ |
Register Instructions
These 1-byte, 2-cycle instructions transfer data between registers. `TXS` is unique in that it does not affect any flags. Affects Flags: N, Z (except TXS)
Mnemonic | Description | HEX |
---|---|---|
TAX | Transfer A to X | $AA |
TAY | Transfer A to Y | $A8 |
TXA | Transfer X to A | $8A |
TYA | Transfer Y to A | $98 |
TSX | Transfer Stack Pointer to X | $BA |
TXS | Transfer X to Stack Pointer | $9A |
ROL (ROtate Left)
Rotates an operand left by one bit. The old bit 7 is moved to the Carry flag, and the old Carry flag is moved into bit 0. Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Accumulator | ROL A | $2A | 1 | 2 |
Zero Page | ROL $44 | $26 | 2 | 5 |
Zero Page,X | ROL $44,X | $36 | 2 | 6 |
Absolute | ROL $4400 | $2E | 3 | 6 |
Absolute,X | ROL $4400,X | $3E | 3 | 7 |
ROR (ROtate Right)
Rotates an operand right by one bit. The old bit 0 is moved to the Carry flag, and the old Carry flag is moved into bit 7. Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Accumulator | ROR A | $6A | 1 | 2 |
Zero Page | ROR $44 | $66 | 2 | 5 |
Zero Page,X | ROR $44,X | $76 | 2 | 6 |
Absolute | ROR $4400 | $6E | 3 | 6 |
Absolute,X | ROR $4400,X | $7E | 3 | 7 |
RTI (ReTurn from Interrupt)
Restores the processor state after an interrupt by pulling the processor status register and program counter from the stack. Affects Flags: all
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Implied | RTI | $40 | 1 | 6 |
RTS (ReTurn from Subroutine)
Returns from a subroutine by pulling the program counter from the stack and incrementing it. Can be used to implement powerful jump tables by pushing crafted return addresses onto the stack. Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Implied | RTS | $60 | 1 | 6 |
SBC (SuBtract with Carry)
Subtracts memory and an inverted Carry flag (borrow) from the accumulator. To perform an 8-bit subtraction, a preceding `SEC` (to indicate "no borrow") is required. The `D` flag enables BCD arithmetic. Affects Flags: N, V, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | SBC #$44 | $E9 | 2 | 2 |
Zero Page | SBC $44 | $E5 | 2 | 3 |
Zero Page,X | SBC $44,X | $F5 | 2 | 4 |
Absolute | SBC $4400 | $ED | 3 | 4 |
Absolute,X | SBC $4400,X | $FD | 3 | 4+ |
Absolute,Y | SBC $4400,Y | $F9 | 3 | 4+ |
Indirect,X | SBC ($44,X) | $E1 | 2 | 6 |
Indirect,Y | SBC ($44),Y | $F1 | 2 | 5+ |
Stack Instructions
These instructions interact with the hardware stack located at page one ($0100-$01FF). The 6502 stack pointer grows downwards. Affects Flags: all (for PLP) or none
Mnemonic | Description | HEX | TIM |
---|---|---|---|
PHA | PusH Accumulator | $48 | 3 |
PLA | PuLl Accumulator | $68 | 4 |
PHP | PusH Processor status | $08 | 3 |
PLP | PuLl Processor status | $28 | 4 |
Store Instructions
Store instructions copy the content of a register to memory. They do not affect any flags. Note the addressing mode asymmetries, particularly the absence of accumulator-relative addressing and the presence of `STX zp,Y` and `STY zp,X`.
STA (STore Accumulator)
Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | STA $44 | $85 | 2 | 3 |
Zero Page,X | STA $44,X | $95 | 2 | 4 |
Absolute | STA $4400 | $8D | 3 | 4 |
Absolute,X | STA $4400,X | $9D | 3 | 5 |
Absolute,Y | STA $4400,Y | $99 | 3 | 5 |
Indirect,X | STA ($44,X) | $81 | 2 | 6 |
Indirect,Y | STA ($44),Y | $91 | 2 | 6 |
STX (STore X register)
Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | STX $44 | $86 | 2 | 3 |
Zero Page,Y | STX $44,Y | $96 | 2 | 4 |
Absolute | STX $4400 | $8E | 3 | 4 |
STY (STore Y register)
Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | STY $44 | $84 | 2 | 3 |
Zero Page,X | STY $44,X | $94 | 2 | 4 |
Absolute | STY $4400 | $8C | 3 | 4 |
Stable & Semi-Stable Illegal Opcodes
This section details non-standard opcodes that are generally stable on NMOS 6502 and its direct variants. They often combine two standard operations into one, saving bytes and/or cycles. "Semi-stable" opcodes are marked and should be used with an understanding of their specific quirks, which are detailed in their descriptions.
SLO (ASO)
Function: ` {addr} = {addr} * 2`, then `A = A OR {addr}` (ASL followed by ORA)
Performs an `ASL` on a memory location, then `ORA`s the new value with the accumulator. Useful for multi-byte shifts where the result must be combined into a register.
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | SLO $44 | $07 | 2 | 5 |
Zero Page,X | SLO $44,X | $17 | 2 | 6 |
Absolute | SLO $4400 | $0F | 3 | 6 |
Absolute,X | SLO $4400,X | $1F | 3 | 7 |
Absolute,Y | SLO $4400,Y | $1B | 3 | 7 |
Indirect,X | SLO ($44,X) | $03 | 2 | 8 |
Indirect,Y | SLO ($44),Y | $13 | 2 | 8 |
Example: A 24-bit shift where the high byte is also needed in A.
; Assuming A is zero before this sequence: SLO data+2 ; Shifts data+2, A now holds the result ROL data+1 ROL data+0 ; This saves an LDA instruction compared to the standard ASL/ROL sequence.
RLA
Function: `{addr} = ROL {addr}`, then `A = A AND {addr}` (ROL followed by AND)
Performs a `ROL` on memory, then `AND`s the new value with the accumulator. Excellent for scrolling effects where a rotated tile needs to be masked by a background.
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | RLA $44 | $27 | 2 | 5 |
Zero Page,X | RLA $44,X | $37 | 2 | 6 |
Absolute | RLA $4400 | $2F | 3 | 6 |
Absolute,X | RLA $4400,X | $3F | 3 | 7 |
Absolute,Y | RLA $4400,Y | $3B | 3 | 7 |
Indirect,X | RLA ($44,X) | $23 | 2 | 8 |
Indirect,Y | RLA ($44),Y | $33 | 2 | 8 |
Example: Combining a sliding sprite with a background mask.
; Standard method (16 bytes, 18 cycles): ROL scroll_gfx LDA scroll_gfx AND background_mask STA screen_ram ; Faster method (12 bytes, 14 cycles): LDA background_mask RLA scroll_gfx ; shift left and combine in one go STA screen_ram
SRE (LSE)
Function: `{addr} = LSR {addr}`, then `A = A EOR {addr}` (LSR followed by EOR)
Performs an `LSR` on memory, then `EOR`s the new value with the accumulator.
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | SRE $44 | $47 | 2 | 5 |
Zero Page,X | SRE $44,X | $57 | 2 | 6 |
Absolute | SRE $4400 | $4F | 3 | 6 |
Absolute,X | SRE $4400,X | $5F | 3 | 7 |
Absolute,Y | SRE $4400,Y | $5B | 3 | 7 |
Indirect,X | SRE ($44,X) | $43 | 2 | 8 |
Indirect,Y | SRE ($44),Y | $53 | 2 | 8 |
RRA
Function: `{addr} = ROR {addr}`, then `A = A ADC {addr}` (ROR followed by ADC)
Performs a `ROR` on memory, then adds the new value with carry to the accumulator. Inherits the decimal mode dependency from `ADC`.
Affects Flags: N, V, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | RRA $44 | $67 | 2 | 5 |
Zero Page,X | RRA $44,X | $77 | 2 | 6 |
Absolute | RRA $4400 | $6F | 3 | 6 |
Absolute,X | RRA $4400,X | $7F | 3 | 7 |
Absolute,Y | RRA $4400,Y | $7B | 3 | 7 |
Indirect,X | RRA ($44,X) | $63 | 2 | 8 |
Indirect,Y | RRA ($44),Y | $73 | 2 | 8 |
SAX (AXS)
Function: `{addr} = A & X`
Stores the result of a bitwise `AND` between the A and X registers into memory. The A and X registers themselves are not modified, and no flags are affected.
Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | SAX $44 | $87 | 2 | 3 |
Zero Page,Y | SAX $44,X | $97 | 2 | 4 |
Absolute | SAX $4400 | $8F | 3 | 4 |
Indirect,X | SAX ($44,X) | $83 | 2 | 6 |
LAX
Function: `A, X = {addr}`
Loads both the A and X registers with the same value from memory. Saves a byte and cycles over a standard `LDA`/`TAX` pair.
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | LAX $44 | $A7 | 2 | 3 |
Zero Page,Y | LAX $44,Y | $B7 | 2 | 4 |
Absolute | LAX $4400 | $AF | 3 | 4 |
Absolute,Y | LAX $4400,Y | $BF | 3 | 4+ |
Indirect,X | LAX ($44,X) | $A3 | 2 | 6 |
Indirect,Y | LAX ($44),Y | $B3 | 2 | 5+ |
DCP (DCM)
Function: `{addr} = {addr} - 1`, then `A CMP {addr}` (DEC followed by CMP)
Decrements a memory location, then compares the new value with the accumulator. Excellent for loop counters.
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | DCP $44 | $C7 | 2 | 5 |
Zero Page,X | DCP $44,X | $D7 | 2 | 6 |
Absolute | DCP $4400 | $CF | 3 | 6 |
Absolute,X | DCP $4400,X | $DF | 3 | 7 |
Absolute,Y | DCP $4400,Y | $DB | 3 | 7 |
Indirect,X | DCP ($44,X) | $C3 | 2 | 8 |
Indirect,Y | DCP ($44),Y | $D3 | 2 | 8 |
ISC (ISB, INS)
Function: `{addr} = {addr} + 1`, then `A = A SBC {addr}` (INC followed by SBC)
Increments a memory location, then subtracts the new value from the accumulator. Inherits decimal mode dependency from `SBC`.
Affects Flags: N, V, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Zero Page | ISC $44 | $E7 | 2 | 5 |
Zero Page,X | ISC $44,X | $F7 | 2 | 6 |
Absolute | ISC $4400 | $EF | 3 | 6 |
Absolute,X | ISC $4400,X | $FF | 3 | 7 |
Absolute,Y | ISC $4400,Y | $FB | 3 | 7 |
Indirect,X | ISC ($44,X) | $E3 | 2 | 8 |
Indirect,Y | ISC ($44),Y | $F3 | 2 | 8 |
Example: A loop that counts up to a value in A.
; Instead of INC counter / LDA counter / CMP #END_VALUE LDA #END_VALUE SEC loop: ISC counter ; INC counter, then SBC counter. Z will be set when they match. BNE loop
ANC
Function: `A = A & #{imm}`, then `C = N`
Performs a standard `AND` immediate, but also copies the resulting N flag (bit 7 of A) into the C flag. This is an excellent way to perform a mask and a bit test in a single, 2-cycle instruction.
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | ANC #$44 | $0B | 2 | 2 |
Immediate | ANC #$44 | $2B | 2 | 2 |
Example: Test bit 7 and branch, without needing to preserve the Carry flag.
; Instead of PHP / AND #$80 / BEQ ... PLP ANC #$80 ; Sets C=1 if bit 7 is set, N=1 if bit 7 is set, Z=0 if bit 7 is set. BCC bit_is_clear
ALR (ASR)
Function: `A = (A & #{imm}) / 2` (AND immediate followed by LSR A)
Performs an `AND` immediate, then performs a logical shift right on the accumulator.
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | ALR #$44 | $4B | 2 | 2 |
ARR
Function: `A = (A & #{imm})`, then a complex `ROR`-like operation.
Performs an `AND` immediate, then rotates the accumulator right. Warning: Flag calculation is unusual and decimal mode dependent. After the `AND`, V is set by `(A bit 6) EOR (A bit 7)`. During the rotate, C is set from the original A bit 6, and the new bit 7 is set from the original C flag. Bit 0 is lost. Due to its complexity, it is rarely used.
Affects Flags: N, V, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | ARR #$44 | $6B | 2 | 2 |
SBX (AXS)
Function: `X = (A & X) - #{imm}`
Calculates `A & X`, then subtracts an immediate value from this temporary result, storing the final value in X. Flags are set as if from a `CMP` instruction (`(A & X) >= imm` sets the Carry). Does not respect decimal mode and is not affected by the initial state of the Carry flag.
Affects Flags: N, Z, C
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Immediate | SBX #$44 | $CB | 2 | 2 |
Example: A faster decrement of X by a constant value.
; Standard method (8 cycles, 5 bytes): TXA SEC SBC #$10 TAX ; Faster method (4 cycles, 3 bytes): TXA ; A and X are now equal, so (A & X) = X. SBX #$10 ; C flag state before this instruction is irrelevant.
'Unstable High Byte' Opcodes
The following opcodes are semi-stable. They combine a load or store operation with a bitwise `AND`, but their behavior can be unreliable under specific hardware conditions. Warning:
- Page Boundary Crossing: If the effective address calculation (`address + index`) crosses a page boundary, the result can be unpredictable. Avoid crossing page boundaries with these instructions.
- Hardware Dependency: The `AND` operation part of the instruction may fail if the CPU's RDY line is pulled low during a specific cycle (e.g., by sprite DMA). This makes the instruction behave like a standard store (`STA`/`STX`/`STY`). To mitigate this, one can use a target address where the high byte is `$FE`, so the `AND` with `(HighByte+1)` becomes an `AND` with `$FF`, which has no effect.
SHA (AXA, AHX)
(Semi-Stable)
Function: `{addr} = A & X & (HighByte({addr}) + 1)`
Stores the result of `A AND X AND (High Byte of target address + 1)` into memory. See warnings above.
Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Absolute,Y | SHA $4400,Y | $9F | 3 | 5 |
Indirect,Y | SHA ($44),Y | $93 | 2 | 6 |
SHX (SXA)
(Semi-Stable)
Function: `{addr} = X & (HighByte({addr}) + 1)`
Stores the result of `X AND (High Byte of target address + 1)` into memory. See warnings above.
Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Absolute,Y | SHX $4400,Y | $9E | 3 | 5 |
SHY (SYA)
(Semi-Stable)
Function: `{addr} = Y & (HighByte({addr}) + 1)`
Stores the result of `Y AND (High Byte of target address + 1)` into memory. See warnings above.
Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Absolute,X | SHY $4400,X | $9C | 3 | 5 |
LAS
(Semi-Stable)
Function: `A, X, S = {addr} & S`
Loads memory, `AND`s it with the Stack Pointer, and loads the result into A, X, and the Stack Pointer. See warnings above.
Affects Flags: N, Z
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Absolute,Y | LAS $4400,Y | $BB | 3 | 4+ |
TAS (SHS)
(Semi-Stable)
Function: `S = A & X`, then `{addr} = S & (HighByte({addr}) + 1)`
Calculates `A & X` and puts the result in the Stack Pointer. Then it `AND`s this new S value with `(High Byte of target address + 1)` and stores the result in memory. See warnings above.
Affects Flags: none
Mode | Syntax | HEX | LEN | TIM |
---|---|---|---|---|
Absolute,Y | TAS $4400,Y | $9B | 3 | 5 |
Attribution
This document was derived by combining information from the following sources:
- http://www.6502.org/tutorials/6502opcodes.html
- https://www.esocop.org/docs/MOS6510UnintendedOpcodes-20152412.pdf
- https://www.masswerk.at/6502/6502_instruction_set.html