A 6502 die

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 2600/8-bit family/5200/7800 Programming, Commodore PET/VIC/64/128 Programming, Acorn 8 Bit Programming, Apple I/II Programming, NES Programming or Super NES Programming.

Syntax

Syntax will vary between assemblers - this book will use the following syntax throughout:

Numerical representations
SyntaxBaseExample
%00001111BinaryLDA #%0001
$FAHexadecimalLDA #$0E
123DecimalLDA #100

Registers

Registers
RegisterSize (bits)Purpose
Accumulator (A)8 Used to perform calculations on data.
Instructions can operate directly on the accumulator instead of spending CPU cycles to access memory
X register (X)8 Used as an index in some addressing modes
Y register (Y)8 Used as an index in some addressing modes
Program Counter (PC)16 Points to the address of the next instruction to be executed
Stack Pointer (SP)8 Stores the stack index into which the next stack element will be inserted.
The address of this position is $0100 + SP. SP is initially set to $FD
Status (SR)8 Each bit represents a status flag. Flags indicate the state of the CPU, or information about the result of the previous instruction.
See the table below for a description of each flag

Status Flags
BitSymbolNameDescription
7NNegative

Compare: Set if the register's value is less than the input value
Otherwise: Set if the result was negative, i.e. bit 7 of the result was set

6VOverflow

Arithmetic: Set if a signed overflow occurred during addition or subtraction, i.e. the sign of the result differs from the sign of both the input and the accumulator
BIT: Set to bit 6 of the input

5-(Unused) Always set
4 B[1] Break Set if an interrupt request has been triggered by a BRK instruction
3DDecimal Decimal mode: mathematical instructions will treat the inputs and outputs as decimal numbers.
E.g. $09 + $01 = $10
2IInterrupt Disable Disables interrupts while set
1ZZero

Compare: Set if the register's value is equal to the input value
BIT: Set if the result of logically ANDing the accumulator with the input results in 0
Otherwise: Set if result was zero

0CCarry Carry/Borrow flag used in math and rotate operations

Arithmetic: Set if an unsigned overflow occurred during addition or subtraction, i.e. the result is less than the initial value
Compare: Set if register's value is greater than or equal to the input value Shifting: Set to the value of the eliminated bit of the input, i.e. bit 7 when shifting left, or bit 0 when shifting right

Memory layout

16-bit values are stored in memory in little-endian, so the least significant byte is stored before the most significant. E.g. if address $0000 contains $FF and address $0001 contains $00, reading a two-byte value from $0000 will result in $00FF.

Signed integers are in two's complement and can represent values from -128 (%11111111) to +127 (%01111111). Bit 7 is set if the integer is negative.

The 6502's program counter is 16 bits wide, so up to 2^16 (65536) bytes of memory are addressable. Certain regions of memory are reserved for particular purposes:

Memory regions
RegionContentsDescription
$0000 - $00FF Zero pageThe first page of memory, which is faster to access than other pages.
Instructions can specify addresses within the zero page with a single byte as opposed to two, so instructions that use the zero page instead of any other page require one less CPU cycle to execute
$0100 - $01FF StackLast-in first-out data structure. Grows backwards from $01FF to $0100.
Used by some transfer, stack, and subroutine instructions
$0200 - $FFFF General-purposeMemory that can be used for whatever purpose needed.
Devices that use the 6502 processor may choose to reserve sub-regions for other purposes, such as memory-mapped I/O

Memory Addressing Modes

Each instruction uses one of thirteen memory addressing modes, which determines the operand of the instruction. An example is provided for each.

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

The value at address $D010 is loaded into the X register.

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

The value at address $0002 is loaded into the Y register.

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 Indirect: (a)

The little-endian two-byte value stored at the specified address is used to perform the computation. Only used by the JMP instruction.

Example

The addresses $A001 and $A002 are read, returning $FF and $00 respectively. The address $00FF is then jumped to.

JMP ($A001)

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.

ADC $C001,X

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 Accumulator is then exclusive ORed with the value $2F at $C238.

EOR ($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.

Load and Store

Load Accumulator with Memory: LDA    Load Index X with Memory: LDX    Load Index Y with Memory: LDY   

M -> A

Flags: N, Z

M -> X

Flags: N, Z

M -> Y

Flags: N, Z

Addressing ModeOpcode
aAD
a,xBD
a,yB9
#A9
zpA5
(zp,x)A1
zp,xB5
(zp),yB1
Addressing ModeOpcode
aAE
a,yBE
#A2
zpA6
zp,yB6
Addressing ModeOpcode
aAC
a,xBC
#A0
zpA4
zp,xB4
Store Accumulator in Memory: STA    Store Index X in Memory: STX    Store Index Y in Memory: STY   

A -> M

Flags: none

X -> M

Flags: none

Y -> M

Flags: none

Addressing ModeOpcode
a8D
a,x9D
a,y99
zp85
(zp,x)81
zp,x95
(zp),y91
Addressing ModeOpcode
a8E
zp86
zp,y96
Addressing ModeOpcode
a8C
zp84
zp,x94

Arithmetic

Add Memory to Accumulator with Carry: ADC    Subtract Memory from Accumulator with Borrow: SBC   

A + M + C -> A

Flags: N, V, Z, C

A - M - ~C -> A

Flags: N, V, Z, C

Addressing ModeOpcode
a6D
a,x7D
a,y79
#69
zp65
(zp,x)61
zp,x75
(zp),y71
Addressing ModeOpcode
aED
a,xFD
a,yF9
#E9
zpE5
(zp,x)E1
zp,xF5
(zp),yF1

Increment and Decrement

Increment Memory by One: INC    Increment Index X by One: INX    Increment Index Y by One: INY   

M + 1 -> M

Flags: N, Z

X + 1 -> X

Flags: N, Z

Y + 1 -> Y

Flags: N, Z

Addressing ModeOpcode
aEE
a,xFE
zpE6
zp,xF6
Addressing ModeOpcode
iE8
Addressing ModeOpcode
iC8
Decrement Memory by One: DEC    Decrement Index X by One: DEX    Decrement Index Y by One: DEY   

M - 1 -> M

Flags: N, Z

X - 1 -> X

Flags: N, Z

Y - 1 -> Y

Flags: N, Z

Addressing ModeOpcode
aCE
a,xDE
zpC6
zp,xD6
Addressing ModeOpcode
iCA
Addressing ModeOpcode
i88

Shift and Rotate

Arithmetic Shift Left One Bit: ASL    Logical Shift Right One Bit: LSR   

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

Flags: N, Z, C

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

Flags: N, Z, C

Addressing ModeOpcode
a0E
a,x1E
A0A
zp06
zp,x16
Addressing ModeOpcode
a4E
a,x5E
A4A
zp46
zp,x56
Rotate Left One Bit: ROL    Rotate Right One Bit: ROR   

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

Flags: N, Z, C

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

Flags: N, Z, C

Addressing ModeOpcode
a2E
a,x3E
A2A
zp26
zp,x36
Addressing ModeOpcode
a6E
a,x7E
A6A
zp66
zp,x76

Logic

AND Memory with Accumulator: AND    OR Memory with Accumulator: ORA   

A & M -> A

Flags: N, Z

A | M -> A

Flags: N, Z

Addressing ModeOpcode
a2D
a,x3D
a,y39
#29
zp25
(zp,x)21
zp,x35
(zp),y31
Addressing ModeOpcode
a0D
a,x1D
a,y19
#09
zp05
(zp,x)01
zp,x15
(zp),y11

Exclusive-OR Memory with Accumulator: EOR

A ^ M -> A

Flags: N, Z

Addressing ModeOpcode
a4D
a,x5D
a,y59
#49
zp45
(zp,x)41
zp,x55
(zp),y51

Compare and Test Bit

The Negative (N), Zero (Z), and Carry (C) status flags are used for conditional (branch) instructions.

All Compare instructions affect flags in the same way:

ConditionNZC
Register < Memory100
Register = Memory011
Register > Memory001
Compare Memory and Accumulator: CMP    Compare Memory and Index X: CPX    Compare Memory with Index Y: CPY   

A - M

Flags: N, Z, C

X - M

Flags: N, Z, C

Y - M

Flags: N, Z, C

Addressing ModeOpcode
aCD
a,xDD
a,yD9
#C9
zpC5
(zp,x)C1
zp,xD5
(zp),yD1
Addressing ModeOpcode
aEC
#E0
zpE4
Addressing ModeOpcode
aCC
#C0
zpC4

Test Bits in Memory with Accumulator: BIT

A & M

Flags: N = M7, V = M6, Z

Addressing ModeOpcode
a2C
#89
zp24

Branch

Branch on Carry Clear: BCC    Branch on Carry Set: BCS   

Branch if C = 0

Flags: none

Branch if C = 1

Flags: none

Addressing ModeOpcode
r90
Addressing ModeOpcode
rB0
Branch on Result not Zero: BNE    Branch on Result Zero: BEQ   

Branch if Z = 0

Flags: none

Branch if Z = 1

Flags: none

Addressing ModeOpcode
rD0
Addressing ModeOpcode
rF0
Branch on Result Plus: BPL    Branch on Result Minus: BMI   

Branch if N = 0

Flags: none

Branch if N = 1

Flags: none

Addressing ModeOpcode
r10
Addressing ModeOpcode
r30
Branch on Overflow Clear: BVC    Branch on Overflow Set: BVS   

Branch if V = 0

Flags: none

Branch if V = 1

Flags: none

Addressing ModeOpcode
r50
Addressing ModeOpcode
r70

Transfer

Transfer Accumulator to Index X: TAX    Transfer Index X to Accumulator: TXA   

A -> X

Flags: N, Z

X -> A

Flags: N, Z

Addressing ModeOpcode
iAA
Addressing ModeOpcode
i8A
Transfer Accumulator to Index Y: TAY    Transfer Index Y to Accumulator: TYA   

A -> Y

Flags: N, Z

Y -> A

Flags: N, Z

Addressing ModeOpcode
iA8
Addressing ModeOpcode
i98
Transfer Stack Pointer to Index X: TSX    Transfer Index X to Stack Pointer: TXS   

S -> X

Flags: N, Z

X -> S

Flags: none

Addressing ModeOpcode
iBA
Addressing ModeOpcode
i9A

Stack

Push Accumulator on Stack: PHA    Pull Accumulator from Stack: PLA   

A -> S

Flags: none

S -> A

Flags: N, Z

Addressing ModeOpcode
i48
Addressing ModeOpcode
i68
Push Processor Status on Stack: PHP    Pull Processor Status from Stack: PLP   

P -> S

Flags: none

S -> P

Flags: all

Addressing ModeOpcode
i08
Addressing ModeOpcode
i28

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

Subroutines and Jump

Jump to New Location: JMP

Jump to new location by changing the value of the program counter.

Warning: When used with the absolute indirect addressing mode, a hardware bug can result in unexpected behavior when the specified address is $xxFF.
E.g. JMP $(11FF) will read the low byte from $11FF and the high byte from $1100, instead of reading the high byte from $1200 as one would expect. This is due to an overflow in the lower byte of the indirect address not being carried into the upper byte.

Flags: none

Addressing ModeOpcode
a4C
(a)6C

Jump to New Location Saving Return Address: JSR

Jumps to a subroutine

The address before the next instruction (PC - 1) is pushed onto the stack: first the upper byte followed by the lower byte. As the stack grows backwards, the return address is therefore stored as a little-endian number in memory.
PC is set to the target address.

Flags: none

Addressing ModeOpcode
a20

Return from Subroutine: RTS

Return from a subroutine to the point where it called with JSR.

The return address is popped from the stack (low byte first, then high byte).
The return address is incremented and stored in PC.

Flags: none

Addressing ModeOpcode
i60

Return from Interrupt: RTI

Return from an interrupt.

SR is popped from the stack.
PC is popped from the stack.

Flags: all

Addressing ModeOpcode
i40

Set and Clear

Clear Carry Flag: CLC    Set Carry Flag: SEC   

0 -> C

Flags: C = 0

1 -> C

Flags: C = 1

Addressing ModeOpcode
i18
Addressing ModeOpcode
i38
Clear Decimal Mode: CLD    Set Decimal Mode: SED   

0 -> D

Flags: D = 0

1 -> D

Flags: D = 1

Addressing ModeOpcode
iD8
Addressing ModeOpcode
iF8
Clear Interrupt Disable Status: CLI    Set Interrupt Disable Status: SEI   

0 -> I

Flags: I = 0

1 -> I

Flags: I = 1

Addressing ModeOpcode
i58
Addressing ModeOpcode
i78
Clear Overflow Flag: CLV   

0 -> V

Flags: V = 0

Addressing ModeOpcode
iB8

Miscellaneous

Break: BRK   

Force an Interrupt

Flags: B = 1, I = 1

Addressing ModeOpcode
i00

No Operation: NOP   

No Operation

Flags: none

Addressing ModeOpcode
iEA

Instruction table

Instruction table
High nibbleLow nibble
000102030405060708090A0B0C0D0E0F
00BRK iORA (zp,x)ORA zpASL zpPHP iORA #ASL AORA aASL a
10BPL rORA (zp),yORA zp,xASL zp,xCLC iORA a,yORA a,xASL a,x
20JSR aAND (zp,x)BIT zpAND zpROL zpPLP iAND #ROL ABIT aAND aROL a
30BMI rAND (zp),yAND zp,xROL zp,xSEC iAND a,yAND a,xROL a,x
40RTI iEOR (zp,x)EOR zpLSR zpPHA iEOR #LSR AJMP aEOR aLSR a
50BVC rEOR (zp),yEOR zp,xLSR zp,xCLI iEOR a,yEOR a,xLSR a,x
60RTS iADC (zp,x)ADC zpROR zpPLA iADC #ROR AJMP (a)ADC aROR a
70BVS rADC (zp),yADC zp,xROR zp,xSEI iADC a,yADC a,xROR a,x
80STA (zp,x)STY zpSTA zpSTX zpDEY iTXA iSTY aSTA aSTX a
90BCC rSTA (zp),ySTY zp,xSTA zp,xSTX zp,yTYA iSTA a,yTXS iSTA a,x
A0LDY #LDA (zp,x)LDX #LDY zpLDA zpLDX zpTAY iLDA #TAX iLDY aLDA aLDX a
B0BCS rLDA (zp),yLDY zp,xLDA zp,xLDX zp,yCLV iLDA a,yTSX iLDY a,xLDA a,xLDX a,y
C0CPY #CMP (zp,x)CPY zpCMP zpDEC zpINY iCMP #DEX iCPY aCMP aDEC a
D0BNE rCMP (zp),yCMP zp,xDEC zp,xCLD iCMP a,yCMP a,xDEC a,x
E0CPX #SBC (zp,x)CPX zpSBC zpINC zpINX iSBC #NOP iCPX aSBC aINC a
F0BEQ rSBC (zp),ySBC zp,xINC zp,xSED iSBC a,ySBC a,xINC a,x

References

  1. , The B flag does not represent an actual CPU register

Further reading

 



This article is issued from Wikibooks. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.