# 6502 Assembly

This book is a guide to the 6502 Assembly language. This book will teach the different memory addressing modes and instructions of the 8-bit 6502 processor.

You might want to learn 6502 assembly language programming if you want to do Atari 8 Bit Programming, Commodore 64 Programming, Acorn 8 Bit Programming, NES Programming or Super NES Programming.

These are the thirteen memory addressing modes for the 6502 processor including some examples.

### Accumulator: A

The Accumulator is implied as the operand, so no address needs to be specified.

Example

Using the ASL (Arithmetic Shift Left) instruction with no operands, the Accumulator is always the value being shifted left.

ASL

### Implied: i

The operand is implied, so it does not need to be specified.

Example

The operands being implied here are X, the source of the transfer, and A, the destination of the transfer.

TXA

### Immediate: #

The operand is used directly to perform the computation.

Example

The value \$22 is loaded into the Accumulator.

LDA #\$22

### Absolute: a

A full 16-bit address is specified and the byte at that address is used to perform the computation.

Example

LDX \$D010

### Zero Page: zp

A single byte specifies an address in the first page of memory (\$00xx), also known as the zero page, and the byte at that address is used to perform the computation.

Example

LDY \$02

### Relative: r

The offset specified is added to the current address stored in the Program Counter (PC). Offsets can range from -128 to +127.

Example

The offset \$2D is added to the address in the Program Counter (say \$C100). The destination of the branch (if taken) will be \$C12D.

BPL \$2D

### Absolute Indexed with X: a,x

The value in X is added to the specified address for a sum address. The value at the sum address is used to perform the computation.

Example

The value \$02 in X is added to \$C001 for a sum of \$C003. The value \$5A at address \$C003 is used to perform the add with carry (ADC) operation.

### Absolute Indexed with Y: a,y

The value in Y is added to the specified address for a sum address. The value at the sum address is used to perform the computation.

Example

The value \$03 in Y is added to \$F001 for a sum of \$F004. The value \$EF at address \$F004 is incremented (INC) and \$F0 is written back to \$F004.

INC \$F001,Y

### Zero Page Indexed with X: zp,x

The value in X is added to the specified zero page address for a sum address. The value at the sum address is used to perform the computation.

Example

The value \$02 in X is added to \$01 for a sum of \$03. The value \$A5 at address \$0003 is loaded into the Accumulator.

LDA \$01,X

### Zero Page Indexed with Y: zp,y

The value in Y is added to the specified zero page address for a sum address. The value at the sum address is used to perform the computation.

Example

The value \$03 in Y is added to \$01 for a sum of \$04. The value \$E3 at address \$0004 is loaded into the Accumulator.

LDA \$01,Y

### Zero Page Indexed Indirect: (zp,x)

The value in X is added to the specified zero page address for a sum address. The little-endian address stored at the two-byte pair of sum address (LSB) and sum address plus one (MSB) is loaded and the value at that address is used to perform the computation.

Example

The value \$02 in X is added to \$15 for a sum of \$17. The address \$D010 at addresses \$0017 and \$0018 will be where the value \$0F in the accumulator is stored.

STA (\$15,X)

### Zero Page Indirect Indexed with Y: (zp),y

The value in Y is added to the address at the little-endian address stored at the two-byte pair of the specified address (LSB) and the specified address plus one (MSB). The value at the sum address is used to perform the computation. Indeed addressing mode actually repeats exactly the accumulator register's digits.

Example

The value \$03 in Y is added to the address \$C235 at addresses \$002A and \$002B for a sum of \$C238. The value \$2F at \$C238 is shifted right (yielding \$17) and written back to \$C238.

LSR (\$2A),Y

## Instructions

These are the instructions for the 6502 processor including an ASCII visual, a list of affected flags, and a table of opcodes for acceptable addressing modes.

M -> A

Flags: N, Z

 Addressing Mode Opcode a AD a,x BD a,y B9 # A9 zp A5 (zp,x) A1 zp,x B5 (zp),y B1

Load Index X with Memory: LDX

M -> X

Flags: N, Z

 Addressing Mode Opcode a AE a,y BE # A2 zp A6 zp,y B6

Load Index Y with Memory: LDY

M -> Y

Flags: N, Z

 Addressing Mode Opcode a AC a,x BC # A0 zp A4 zp,x B4

Store Accumulator in Memory: STA

A -> M

Flags: none

 Addressing Mode Opcode a 8D a,x 9D a,y 99 zp 85 (zp,x) 81 zp,x 95 (zp),y 91

Store Index X in Memory: STX

X -> M

Flags: none

 Addressing Mode Opcode a 8E zp 86 zp,y 96

Store Index Y in Memory: STY

Y -> M

Flags: none

 Addressing Mode Opcode a 8C zp 84 zp,x 94

### Arithmetic

A + M + C -> A

Flags: N, V, Z, C

 Addressing Mode Opcode a 6D a,x 7D a,y 79 # 69 zp 65 (zp,x) 61 zp,x 75 (zp),y 71

Subtract Memory from Accumulator with Borrow: SBC

A - M - ~C -> A

Flags: N, V, Z, C

 Addressing Mode Opcode a ED a,x FD a,y F9 # E9 zp E5 (zp,x) E1 zp,x F5 (zp),y F1

### Increment and Decrement

Increment Memory by One: INC

M + 1 -> M

Flags: N, Z

 Addressing Mode Opcode a EE a,x FE zp E6 zp,x F6

Increment Index X by One: INX

X + 1 -> X

Flags: N, Z

Increment Index Y by One: INY

Y + 1 -> Y

Flags: N, Z

Decrement Memory by One: DEC

M - 1 -> M

Flags: N, Z

 Addressing Mode Opcode a CE a,x DE zp C6 zp,x D6

Decrement Index X by One: DEX

X - 1 -> X

Flags: N, Z

Decrement Index Y by One: DEY

Y - 1 -> Y

Flags: N, Z

### Shift and Rotate

Arithmetic Shift Left One Bit: ASL

C <- 7 6 5 4 3 2 1 0 <- 0

Flags: N, Z, C

 Addressing Mode Opcode a 0E a,x 1E A 0A zp 06 zp,x 16

Logical Shift Right One Bit: LSR

0 -> 7 6 5 4 3 2 1 0 -> C

Flags: N, Z, C

 Addressing Mode Opcode a 4E a,x 5E A 4A zp 46 zp,x 56

Rotate Left One Bit: ROL

C <- 7 6 5 4 3 2 1 0 <- C

Flags: N, Z, C

 Addressing Mode Opcode a 2E a,x 3E A 2A zp 26 zp,x 36

Rotate Right One Bit: ROR

C -> 7 6 5 4 3 2 1 0 -> C

Flags: N, Z, C

 Addressing Mode Opcode a 6E a,x 7E A 6A zp 66 zp,x 76

### Logic

AND Memory with Accumulator: AND

A & M -> A

Flags: N, Z

 Addressing Mode Opcode a 2D a,x 3D a,y 39 # 29 zp 25 (zp,x) 21 zp,x 35 (zp),y 31

OR Memory with Accumulator: ORA

A | M -> A

Flags: N, Z

 Addressing Mode Opcode a 0D a,x 1D a,y 19 # 09 zp 05 (zp,x) 01 zp,x 15 (zp),y 11

Exclusive-OR Memory with Accumulator: EOR

A ^ M -> A

Flags: N, Z

 Addressing Mode Opcode a 4D a,x 5D a,y 59 # 49 zp 45 (zp,x) 41 zp,x 55 (zp),y 51

### Compare and Test Bit

For all Compare instructions:

 Condition N Z C Register < Memory 1 0 0 Register = Memory 0 1 1 Register > Memory 0 0 1

Compare Memory and Accumulator: CMP

A - M

Flags: N, Z, C

 Addressing Mode Opcode a CD a,x DD a,y D9 # C9 zp C5 (zp,x) C1 zp,x D5 (zp),y D1

Compare Memory and Index X: CPX

X - M

Flags: N, Z, C

 Addressing Mode Opcode a EC # E0 zp E4

Compare Memory with Index Y: CPY

Y - M

Flags: N, Z, C

 Addressing Mode Opcode a CC # C0 zp C4

Test Bits in Memory with Accumulator: BIT

A & M

Flags: N = M7, V = M6, Z

 Addressing Mode Opcode a 2C # 89 zp 24

### Branch

Branch on Carry Clear: BCC

Branch if C = 0

Flags: none

Branch on Carry Set: BCS

Branch if C = 1

Flags: none

Branch on Result Zero: BEQ

Branch if Z = 1

Flags: none

Branch on Result Minus: BMI

Branch if N = 1

Flags: none

Branch on Result not Zero: BNE

Branch if Z = 0

Flags: none

Branch on Result Plus: BPL

Branch if N = 0

Flags: none

Branch on Overflow Clear: BVC

Branch if V = 0

Flags: none

Branch on Overflow Set: BVS

Branch if V = 1

Flags: none

### Transfer

Transfer Accumulator to Index X: TAX

A -> X

Flags: N, Z

Transfer Index X to Accumulator: TXA

X -> A

Flags: N, Z

Transfer Accumulator to Index Y: TAY

A -> Y

Flags: N, Z

Transfer Index Y to Accumulator: TYA

Y -> A

Flags: N, Z

Transfer Stack Pointer to Index X: TSX

S -> X

Flags: N, Z

Transfer Index X to Stack Pointer: TXS

X -> S

Flags: none

### Stack

Push Accumulator on Stack: PHA

A -> S

Flags: none

Pull Accumulator from Stack: PLA

S -> A

Flags: N, Z

Push Processor Status on Stack: PHP

P -> S

The processor status is stored as a single byte with the following flags bits from high to low: NV-BDIZC.

Flags: none

Pull Processor Status from Stack: PLP

S -> P

Setting the processor status from the stack is the only way to clear the B (Break) flag.

Flags: all

### Subroutines and Jump

Flags: none

 Addressing Mode Opcode a 4C (a) 6C

Flags: none

Return from Subroutine: RTS

Return from Subroutine

Flags: none

Return from Interrupt: RTI

Return from Interrupt

Flags: all

### Set and Clear

Set Carry Flag: SEC

1 -> C

Flags: C = 1

Set Decimal Mode: SED

1 -> D

Flags: D = 1

Set Interrupt Disable Status: SEI

1 -> I

Flags: I = 1

Clear Carry Flag: CLC

0 -> C

Flags: C = 0

Clear Decimal Mode: CLD

0 -> D

Flags: D = 0

Clear Interrupt Disable Status: CLI

0 -> I

Flags: I = 0

Clear Overflow Flag: CLV

0 -> V

Flags: V = 0

### Miscellaneous

No Operation: NOP

No Operation

Flags: none