6502-Series Assembly Language
Table of Contents
GEOS runs on the Commodore 64, Commodore 128, Commodore Plus/4, and Apple IIe computers, as well as the computers
completely compatible with them. They all use a CPU from the 6502 family of microprocessors:
the 6502 (Apple IIe),
the 65C02 (Apple IIe Enhanced and Apple IIc),
the 6510 (Commodore 64),
the 7501 or 8501 (Commodore Plus/4),
the 8502 (Commodore 128),
the 65CE02 AKA 4510 (Commodore 65),
and the 65C816 (CMD SuperCPU and Apple IIgs).
The most common language to program in for GEOS is in 6502 assembly language with a macro assembler.
This page is intended to be a quick reference, not a tutorial or necessarily complete reference.
Most of the data on this page is from the Commodore 64 Programmer's Reference Guide and is specific to the
6510 CPU. The only programmer-visible difference between the 6502 and 6510 is the placement of
hardware I/O at memory addresses $0000 and $0001, making them unavailable for use as
storage.
Important: The earliest CPUs in the 6502 series don't have a bra
instruction, including those used in the Commodore
64 and 128, but the later CPUs do. However, this guide's example code appears to make use of a bra
instruction in CPUs
that don't have one. Where it's used in this guide, it refers to to a geoProgrammer macro
called "bra" instead. The macro expands to a clv
followed by bvc
instruction. (Same for "smb," "rmb," "bbs," and
"bbr," although no 6502-series CPUs found in Commodore or Apple 8-bit computers actually use those mnemonics.)
Mnemonic |
Instruction |
Load and Store |
lda |
Load A |
ldx |
Load X |
ldy |
Load Y |
sta |
Store A |
stx |
Store X |
sty |
Store Y |
Arithmetic Math |
adc |
Add with carry to A |
sbc |
Subtract with carry from A |
Increment and Decrement |
inc |
Increment memory |
inx |
Increment X |
iny |
Increment Y |
dec |
Decrement memory |
dex |
Decrement X |
dey |
Decrement Y |
Logical Math |
and |
Bitwise-AND with A |
ora |
Bitwise-OR with A |
eor |
Bitwise exclusive-OR with A |
Jump, Branch, Compare, and Test |
jmp |
Jump |
bcc |
Branch on carry clear |
bcs |
Branch on carry set |
beq |
Branch on equal |
bne |
Branch on not equal |
bmi |
Branch on minus |
bpl |
Branch on plus |
bvs |
Branch on overflow set |
bvc |
Branch on overflow clear |
cmp |
Compare with A |
cpx |
Compare with X |
cpy |
Compare with Y |
bit |
Test bits |
Shift and Rotate |
asl |
Arithmetic shift left |
lsr |
Logical shift right |
rol |
Rotate left |
ror |
Rotate right |
Register Transfer |
tax |
Transfer A to X |
tay |
Transfer A to Y |
txa |
Transfer X to A |
tya |
Transfer Y to A |
Stack Transfer |
tsx |
Transfer stack pointer to X |
txs |
Transfer X to stack pointer |
pha |
Push A to stack |
php |
Push processor flags to stack |
pla |
Pull A from stack |
plp |
Pull processor flags from stack |
Subroutines |
jsr |
Jump saving return or jump to subroutine |
rts |
Return to saved or return from subroutine |
rti |
Return from interrupt |
Set and Clear |
clc |
Clear carry bit |
cld |
Clear decimal mode bit |
cli |
Clear interrupt disable bit |
clv |
Clear overflow bit |
sec |
Set carry bit |
sed |
Set decimal mode bit |
sei |
Set interrupt disable bit |
Special Purpose |
nop |
No operation |
brk |
Break |
6502 Instruction Set Opcodes $00--$7f
Low | High Nybble |
0_ |
1_ |
2_ |
3_ |
4_ |
5_ |
6_ |
7_ |
_0 |
brk |
bpl R |
jsr M |
bmi R |
rti |
bvc R |
rts |
bvs R |
_1 |
ora (Z,x) |
ora (Z),y |
and (Z,x) |
and (Z),y |
eor (Z,x) |
eor (Z),y |
adc (Z,x) |
adc (Z),y |
_2 |
|
|
|
|
|
|
|
|
_3 |
|
|
|
|
|
|
|
|
_4 |
|
|
bit Z |
|
|
|
|
|
_5 |
ora Z |
ora Z,x |
and Z |
and Z,x |
eor Z |
eor Z,x |
adc Z |
adc Z,x |
_6 |
asl Z |
asl Z,x |
rol Z |
rol Z,x |
lsr Z |
lsr Z,x |
ror Z |
ror Z,x |
_7 |
|
|
|
|
|
|
|
|
_8 |
php |
clc |
plp |
sec |
pha |
cli |
pla |
sei |
_9 |
ora # |
ora M,y |
and # |
and M,y |
eor # |
eor M,y |
adc # |
adc M,y |
_a |
asl a |
|
rol a |
|
lsr a |
|
ror a |
|
_b |
|
|
|
|
|
|
|
|
_c |
|
|
bit M |
|
jmp M |
|
jmp (M) |
|
_d |
ora M |
ora M,x |
and M |
and M,x |
eor M |
eor M,x |
adc M |
adc M,x |
_e |
asl M |
asl M,x |
rol M |
rol M,x |
lsr M |
lsr M,x |
ror M |
ror M,x |
_f |
|
|
|
|
|
|
|
|
6502 Instruction Set Opcodes $80--$ff
Low | High Nybble |
8_ |
9_ |
a_ |
b_ |
c_ |
d_ |
e_ |
f_ |
_0 |
|
bcc R |
ldy # |
bcs R |
cpy # |
bne R |
cpx # |
beq R |
_1 |
sta (Z,x) |
sta (Z),y |
lda (z,x) |
lda (Z),y |
cmp (Z,x) |
cmp (Z),y |
sbc (Z,x) |
sbc (Z),y |
_2 |
|
|
ldx # |
|
|
|
|
|
_3 |
|
|
|
|
|
|
|
|
_4 |
sty Z |
sty Z,x |
ldy Z |
ldy Z,x |
cpy Z |
|
cpx Z |
|
_5 |
sta Z |
sta Z,x |
lda Z |
lda Z,x |
cmp Z |
cmp Z,x |
sbc Z |
sbc Z,x |
_6 |
stx Z |
stx Z,y |
ldx Z |
ldx Z,y |
dec Z |
dec Z,x |
inc Z |
inc Z,x |
_7 |
|
|
|
|
|
|
|
|
_8 |
dey |
tya |
tay |
clv |
iny |
cld |
inx |
sed |
_9 |
|
sta M,y |
lda # |
lda M,y |
cmp # |
cmp M,y |
sbc # |
sbc M,y |
_a |
txa |
txs |
tax |
tsx |
dex |
|
nop |
|
_b |
|
|
|
|
|
|
|
|
_c |
sty M |
|
ldy M |
ldy M,x |
cpy M |
|
cpx M |
|
_d |
sta M |
sta M,x |
lda M |
lda M,x |
cmp M |
cmp M,x |
sbc M |
sbc M,x |
_e |
stx M |
|
ldx M |
ldx M,y |
dec M |
dec M,x |
inc M |
inc M,x |
_f |
|
|
|
|
|
|
|
|
Empty opcodes in the tables above map to undefined instructions that are often called "illegal opcodes." The 6502 doesn't
use CPU microcode in the modern sense, so it will try to perform illegal opcode instructions if it encounters one. The
instructions carried out by illegal opcodes are undefined, often vary between CPU models in the 6502 family, and in some
cases cause unpredictable behavior. For example, one such set of opcodes, nicknamed with the mnemonic "jam
," jams the
CPU into a non-functional state; a reset or power cycle is the only way to recover.
Some of the empty opcodes in the tables above are defined and used by later CPUs in the 6502 family for added
functionality, such as access to more registers, wider registers, and larger addressable memory ranges. At the time this
guide was written, the 65C816 was a currently produced and commercially available CPU compatible with the 6502.
6502 Instruction Addressing Modes
Mnemonic |
Bytes |
Mode |
How the Operand Address Is Used |
ins |
1 |
Implied |
Implied by the instruction. |
ins a |
1 |
Accumulator |
Register A. |
ins # |
2 |
Immediate |
Operand is a value. |
ins Z |
2 |
Zero Page |
Given offset into page 0 ($00xx). |
ins Z,x |
2 |
Zero Page Indexed X |
Zero Page plus X. |
ins Z,y |
2 |
Zero Page Indexed Y |
Zero Page plus Y. |
ins M |
3 |
Absolute |
Given offset into given page. |
ins M,x |
3 |
Absolute Indexed X |
Absolute plus X. |
ins M,y |
3 |
Absolute Indexed Y |
Absolute plus Y. |
ins R |
2 |
Relative |
Signed offset from next instruction. |
ins (M) |
3 |
Indirect |
Pointer: Absolute address is pointer. |
ins (Z,x) |
2 |
Indexed Indirect |
Pointer: Zero Page address plus X is pointer. |
ins (Z),y |
2 |
Indirect Indexed |
Pointer plus Y: Zero Page address is pointer. |
In this table, "ins" is a placeholder for any instruction mnemonic. |
Except for Implied and Accumulator modes, which don't take an operand, and Immediate mode, which takes a value as an
operand, all addressing modes take a memory address as an operand.
In Indirect, Indexed Indirect, and Indirect Indexed modes, the values at the operand address and the operand address plus
one are taken as a word pointer to an absolute address in memory. The order of bytes is low byte at low address and high
byte at high address, or offset byte followed by page byte. In Indirect mode (used only by the JMP instruction), the
pointer is used as the jump vector. In Indexed Indirect mode, the value of X is added to the operand to find the
addresses containing the pointer. In Indirect Indexed mode, the operand is the address of the pointer's low byte, and the
value of Y is instead added to the pointer value, not the operand.
The address in Relative mode is a signed byte computed as an offset from the instruction following a branch instruction.
A relative address can be between 126 bytes behind the branch instruction opcode (-128+2) to 129 bytes ahead of it (127+2).
Virtually every assembler will let you assign a label to the branch target address and use that label as the branch
instruction operand, saving you the trouble of converting an absolute address into a relative address. In the assembler
mode of most machine language monitors, the monitor will let you enter a branch to an absolute address and convert the
operand to a relative address for you as well.
In Zero Page Indexed and Indexed Indirect modes, adding the index value to the operand address could result in a computed
address of 256 ($100) or greater. If that happens, the actual computed address will remain in page 0 and simply wrap
around from $00ff to $0000. For example, if you run lda $70,x
when X contains $f1, then the value
A is loaded with will not come from address $0161 as you might think; the overflowing $1 would be discarded,
and A would be loaded from address $0061 instead.
Note that this wrap-around will not happen in Indirect Indexed mode. In Indirect Indexed mode, the values at the operand
address and operand address plus one are taken as a pointer to an absolute address, then the value of Y is added to
that absolute address. For example, if $02 contains $81 and $03 contains $a0, together forming a pointer
to $a081, and Y contains $c1, then running sta ($02),y
would store the value of A in address $a142:
Y ($c1) plus the adddress word at $02 ($a081).
The 6502 is an 8-bit CPU comprised of six registers, a set of 151 CPU operation codes (called "opcodes") expressed as 56
instructions, and one to eight of 13 addressing modes for each instruction. Three of the registers are directly accessible
by the programmer, and three are not. Five of the registers are 8-bit byte-size registers, and one is 16-bit word-size.
6502 CPU Registers
|
Name |
Size |
Purpose |
A |
Accumulator |
byte |
The main general-purpose data register. |
X |
X Index |
byte |
General purpose and offset indexing. |
Y |
Y Index |
byte |
General purpose and offset indexing. |
P |
Processor Status |
byte |
Bit flags indicating CPU status. |
S |
Stack Pointer |
byte |
Pointer to top of stack in page $01. |
PC |
Program Counter |
word |
Address of currently running instruction. |
The Accumulator, the X Index, and the Y Index are the registers directly accessible by the programmer: They can be
directly loaded with byte values, and their values can be directly stored in memory.
The Accumulator, also called the A register, is the only register that can be directly involved in basic arithmetic
operations, and it's the register most often used for general data transformations. The X and Y registers
are used most often for holding counters or offsets for accessing memory, but they can also be used for shuttling data like
the A register. The X register is also the only register that can retrieve or change the Stack Pointer.
The Processor Status register contains seven bit flags indicating various current or recent CPU events. Most instructions
either cause a status flag to change or examine a status flag to determine a course of action.
Processor Status Flags
Bit |
Flag |
Name |
Meaning when clear |
Meaning when set |
7 |
N |
Negative |
A is 0 or positive. |
A is negative. |
6 |
V |
Overflow |
Last arithmetic was between -127 and 128. |
Last arithmetic overflowed or underflowed. |
5 |
|
|
|
|
4 |
B |
Break |
Interrupt caused externally. |
Interrupt caused by BRK. |
3 |
D |
Decimal Mode |
ADC and SBC use binary math. |
ADC and SBC use BCD math. |
2 |
I |
Interrupt Disable |
IRQs are enabled. |
IRQs are disabled (masked). |
1 |
Z |
Zero |
Last computed value was nonzero or unequal. |
Last computed value was 0 or equal. |
0 |
C |
Carry |
Last operation didn't carry. |
Last operation carried. |
The Negative flag is set or cleared based on bit 7 of A.
The Overflow flag is set when the two's-complement result of an addition or subtraction is invalid; that is, when adding
two like-signed numbers or subtracting two different-signed numbers gives an answer greater than 127 or less than -128.
BCD stands for "binary-coded decimal" and is an encoding in which each nybble is limited to holding a decimal digit
($0--$9).
In binary math, adding $05 to $07 gives $0c (12). In BCD math, however, the hex values $a--$f are invalid, so
adding $05 to $07 gives the hex value $12 (18, the BCD encoding for 12).
The ADC and SBC instructions are the only ones that use Decimal Mode.
In GEOS, the D flag is clear by default. If your program enables it with SED, it must disable it again with CLD before
calling any GEOS Kernal routines, or the routines may perform bad math.
The 6502 has two types of interrupts: maskable interrupt requests, called IRQ, and non-maskable interrupt requests, called
NMI. The Interrupt Disable flag affects only IRQs. NMIs will always interrupt the CPU, and the BRK instruction causes an
NMI. Note that because the Interrupt Disable flag is for disabling IRQ, the SEI and CLI instructions do the opposite of
what you might expect: SEI disables IRQ, and CLI enables IRQ.
The stack is a first-in last-out structure. The byte most recently pushed to the stack is the first that will be popped
("pulled" in 6502) from the stack and is said to be at the top of the stack.
The Stack Pointer starts at the end of the stack page ($01), pointing to $01ff. Every time a byte is pushed onto
the stack, 1 is subtracted from the Stack Pointer, so it points to the first free byte in the stack page. Every time a
byte is pulled from the stack, the reverse happens: 1 is added to the Stack Pointer.
Be careful with stack management: If more than 256 bytes are pushed onto the stack, then the Stack Pointer will overflow
and wrap around from $0100 to $01ff, and the bottom of the stack will be overwritten and lost.
The limited set of registers and instructions means that a 6502 programmer has to use an assortment of clever tricks and
boilerplate code to accomplish tasks that more complicated CPUs can perform natively, but it still contains all the
resources necessary to accomplish them.
To help deal with the limited number and capabilities of the registers, the 6502 lets you use the first page of memory
(page 0 or Zero Page) as pseudo-registers via Zero Page addressing modes, which are shorter and faster than their
corresponding Absolute addressing modes.
Programs are most often written for a programming language compiler or assembly langugage assembler and linker. Most
assemblers take code in the form of three-letter instruction mnemonics, followed by an operand and punctuation indicating
the instruction addressing mode. Instructions taking operands must have either a byte-size or word-size number for the
operand; most assemblers allow you to define names to stand in for those numbers, which you can then use as constants,
variables, routines, global labels, local labels, and other kinds of named values.
Source code lines are divided into four fields: an address label, an instruction, its operand, and a comment.
Lines can have any, all, or none of those fields, each separated by any amount of spacing, but they appear in that order.
(However, operands can't appear alone; an operand must be on the same line as its instruction.)
Most assemblers will not let you write more than one instruction per line of source code.
Order of fields in geoAssembler source code lines using an example
Label |
Instruction |
Operand/Mode |
Comment |
PurpleBack: |
lda |
#4 |
|
|
sta |
$d021 |
;Turn the background purple. |
|
rts |
|
|
Every addressing mode taking a numeric operand except one will use that numeric value as an address. Immediate mode is the
exception: It uses the numeric value literally, loading the affected register with that value.
In most assemblers and machine language monitors, you need to use a hash sign or octothorpe (" #
") to signal Immediate
mode addressing. A leading "#" indicates an immediate decimal value, a leading "#$" digraph means an immediate hexadecimal
value, a leading "#%" digraph means an immediate binary value, and (in geoAssembler) a leading "#?" digraph means an
immediate octal value.
For example, lda #15
, lda #$0f
, lda #%00001111
, and lda #?017
compile to the exact same instruction opcode and
operand bytes ($a9 $0f).
The comment character for 6502 code is universally the semi-colon. A comment begins with a semi-colon (" ;
"), and it
ends with the line terminator (ASCII code CR in GEOS). Assembler-specific directives can be abused to produce multi-line
comments, but only the semi-colon single-line comments are ubiquitous.
See other references for more complete primers and actual tutorials for 6502 assembly language programming. Unless you
engage in the surprisingly practical madness of compiling your own assembly code by hand, you should get an assembler and
read its manual as well.
Each mnemonic is described with a summary and two tables. The data is from the Commodore 64 Programmer's Reference
Guide and applies to the 6510 CPU.
First table:
- Operation: A brief expression of the instruction's operation.
- A, X, Y, P, S, PC: Given regester or its value.
- N, V, B, D, I, Z, C: Given bit flag of P register or its value.
- M: Given memory address or its value, or value of Immediate mode operand.
- Flags: A list of flags affected and how.
Second table:
- Mode: An addressing mode available for this instruction.
- Assembly Form: How the instruction is written in source code for this mode.
- Oper: A stand-in symbol or label for the operand value byte.
- OperW: A stand-in symbol or label for the operand value word.
- Hex: The opcode in hexadecimal form.
- Bytes: The total number of bytes used for the opcode and operand.
- Cycles: The total number of CPU cycles it takes to perform the instruction.
Flags:
- N: Negative
- V: Overflow
- B: Break
- D: Decimal
- I: Interrupt
- Z: Zero
- C: Carry
Add memory to accumulator with carry.
This is the only addition instruction; there is no addition without carry.
Performs binary addition when D = 0; performs binary-coded decimal (BCD) addition when D = 1.
The complementary math instruction is sbc
.
Operation |
A + M + C -- Result in A, C |
Flags |
N, V, C, Z -- Set or cleared according to sum. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
adc #Oper |
69 |
2 |
2 |
Zero Page |
adc Oper |
65 |
2 |
3 |
Zero Page Indexed X |
adc Oper,x |
75 |
2 |
4 |
Absolute |
adc OperW |
6d |
3 |
4 |
Absolute Indexed X |
adc OperW,x |
7d |
3 |
4+ |
Absolute Indexed Y |
adc OperW,y |
79 |
3 |
4+ |
Indexed Indirect |
adc (Oper,x) |
61 |
2 |
6 |
Indirect Indexed |
adc (Oper),y |
71 |
2 |
5+ |
+ Add one cycle if page boundary crossed |
Logical AND to the accumulator.
Operation |
A AND M -- Result in A |
Flags |
N, Z -- Set or cleared according to result. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
and #Oper |
29 |
2 |
2 |
Zero Page |
and Oper |
25 |
2 |
3 |
Zero Page Indexed X |
and Oper,x |
35 |
2 |
4 |
Absolute |
and OperW |
2d |
3 |
4 |
Absolute Indexed X |
and OperW,x |
3d |
3 |
4+ |
Absolute Indexed Y |
and OperW,y |
39 |
3 |
4+ |
Indexed Indirect |
and (Oper,x) |
21 |
2 |
6 |
Indirect Indexed |
and (Oper),y |
31 |
2 |
5 |
+ Add one cycle if page boundary crossed |
Arithmetic shift left, or shift memory or accumulator left one bit.
This differs from rol
in that a 0 is shifted in.
The effect is multiplication by 2, or by a power of 2 when repeated.
The complementary shift instruction is lsr
.
Operation |
bit 7 to C; bits 6--0 to bits 7--1; 0 to bit 0 |
Flags |
N, Z -- Set or cleared according to result. C -- From bit 7. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Accumulator |
asl a |
0a |
1 |
2 |
Zero Page |
asl Oper |
06 |
2 |
5 |
Zero Page Indexed X |
asl Oper,x |
16 |
2 |
6 |
Absolute |
asl OperW |
0e |
3 |
6 |
Absolute Indexed X |
asl OperW,x |
1e |
3 |
7 |
Branch on carry clear.
Operation |
Branch on C = 0 |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Relative |
bcc Oper |
90 |
2 |
2+ |
+ Add one cycle if branch taken to same page or two if to another page |
Branch on carry set.
Operation |
Branch on C = 1 |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Relative |
bcs Oper |
b0 |
2 |
2+ |
+ Add one cycle if branch taken to same page or two if to another page |
Branch on equal or result zero.
Operation |
Branch on Z = 1 |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Relative |
beq Oper |
f0 |
2 |
2+ |
+ Add one cycle if branch taken to same page or two if to another page |
Test bits in memory with accumulator.
Operation |
A AND M; M bit 7 to N; M bit 6 to V. |
Flags |
N, V -- From bits 7, 6 of M; Z -- AND result. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Zero Page |
bit Oper |
24 |
2 |
3 |
Absolute |
bit OperW |
2c |
3 |
4 |
Branch on minus or result negative.
Operation |
Branch on N = 1 |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Relative |
bmi Oper |
30 |
2 |
2+ |
+ Add one cycle if branch taken to same page or two if to another page |
Branch on not equal or result not zero.
Operation |
Branch on Z = 0 |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Relative |
bne Oper |
d0 |
2 |
2+ |
+ Add one cycle if branch taken to same page or two if to another page |
Branch on plus or result positive.
Operation |
Branch on N = 0 |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Relative |
bpl Oper |
10 |
2 |
2+ |
+ Add one cycle if branch taken to same page or two if to another page |
Force break interrupt.
A brk
command can't be masked by setting I.
Operation |
PC+2 pushed; flags pushed; PC loaded from $fffe |
Flags |
B, I -- Set to 1 |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
brk |
00 |
1 |
7 |
Branch on overflow clear.
Operation |
Branch on V = 0 |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Relative |
bvc Oper |
50 |
2 |
2+ |
+ Add one cycle if branch taken to same page or two if to another page |
Branch on overflow set.
Operation |
Branch on V = 1 |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Relative |
bvs Oper |
70 |
2 |
2+ |
+ Add one cycle if branch taken to same page or two if to another page |
Clear carry flag.
Operation |
0 to C |
Flags |
C -- Cleared. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
clc |
18 |
1 |
2 |
Clear decimal mode.
After this instruction, adc
and sbc
perform binary arithmetic.
Operation |
0 to D |
Flags |
D -- Cleared. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
cld |
d8 |
1 |
2 |
Clear interrupt disable bit.
This instruction enables IRQ; use sei
to disable IRQ.
Operation |
0 to I |
Flags |
I -- Cleared. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
cli |
58 |
1 |
2 |
Clear overflow flag.
Operation |
0 to V |
Flags |
V -- Cleared. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
clv |
b8 |
1 |
2 |
Compare memory and accumulator.
Operation |
A - M |
Flags |
N, Z, C -- Set or cleared according to difference. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
cmp #Oper |
c9 |
2 |
2 |
Zero Page |
cmp Oper |
c5 |
2 |
3 |
Zero Page Indexed X |
cmp Oper,x |
d5 |
2 |
4 |
Absolute |
cmp OperW |
cd |
3 |
4 |
Absolute Indexed X |
cmp OperW,x |
dd |
3 |
4+ |
Absolute Indexed Y |
cmp OperW,y |
d9 |
3 |
4+ |
Indexed Indirect |
cmp (Oper,x) |
c1 |
2 |
6 |
Indirect Indexed |
cmp (Oper),y |
d1 |
2 |
5+ |
+ Add one cycle if page boundary crossed |
Compare memory and X Index.
Operation |
X - M |
Flags |
N, Z, C -- Set or cleared according to difference. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
cpx #Oper |
e0 |
2 |
2 |
Zero Page |
cpx Oper |
e4 |
2 |
3 |
Absolute |
cpx OperW |
ec |
3 |
4 |
Compare memory and Y Index.
Operation |
Y - M |
Flags |
N, Z, C -- Set or cleared according to difference. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
cpy #Oper |
c0 |
2 |
2 |
Zero Page |
cpy Oper |
c4 |
2 |
3 |
Absolute |
cpy OperW |
cc |
3 |
4 |
Decrement memory by one.
Operation |
M - 1 -- Result in M |
Flags |
N, Z -- Set or cleared according to difference. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Zero Page |
dec Oper |
c6 |
2 |
5 |
Zero Page Indexed X |
dec Oper,x |
d6 |
2 |
6 |
Absolute |
dec OperW |
ce |
3 |
6 |
Absolute Indexed X |
dec OperW,x |
de |
3 |
7 |
Decrement X Index by one.
Operation |
X - 1 -- Result in X |
Flags |
N, Z -- Set or cleared according to difference. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
dex |
ca |
1 |
2 |
Decrement Y Index by one.
Operation |
Y - 1 -- Result in Y |
Flags |
N, Z -- Set or cleared according to difference. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
dey |
88 |
1 |
2 |
Logical exclusive-OR to the accumulator.
Operation |
A exclusive-OR M -- Result in A |
Flags |
N, Z -- Set or cleared according to result. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
eor #Oper |
49 |
2 |
2 |
Zero Page |
eor Oper |
45 |
2 |
3 |
Zero Page Indexed X |
eor Oper,x |
55 |
2 |
4 |
Absolute |
eor OperW |
4d |
3 |
4 |
Absolute Indexed X |
eor OperW,x |
5d |
3 |
4+ |
Absolute Indexed Y |
eor OperW,y |
59 |
3 |
4+ |
Indexed Indirect |
eor (Oper,x) |
41 |
2 |
6 |
Indirect Indexed |
eor (Oper),y |
51 |
2 |
5+ |
+ Add one cycle if page boundary crossed |
Increment memory by one.
Operation |
M + 1 -- Result in M |
Flags |
N, Z -- Set or cleared according to sum. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Zero Page |
inc Oper |
e6 |
2 |
5 |
Zero Page Indexed X |
inc Oper,x |
f6 |
2 |
6 |
Absolute |
inc OperW |
ee |
3 |
6 |
Absolute Indexed X |
inc OperW,x |
fe |
3 |
7 |
Increment X Index by one.
Operation |
X + 1 -- Result in X |
Flags |
N, Z -- Set or cleared according to sum. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
inx |
e8 |
1 |
2 |
Increment Y Index by one.
Operation |
Y + 1 -- Result in Y |
Flags |
N, Z -- Set or cleared according to sum. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
iny |
c8 |
1 |
2 |
Jump to new location.
Operation |
PC + 1, PC + 2 -- To PC low, PC high |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Absolute |
jmp OperW |
4c |
3 |
3 |
Indirect |
jmp (OperW) |
6c |
3 |
5 |
Jump to new location saving return address, or jump to subroutine.
Operation |
PC + 2 pushed; PC + 1, PC + 2 -- To PC low, PC high |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Absolute |
jsr OperW |
20 |
3 |
6 |
Load accumulator with memory.
Operation |
M to A |
Flags |
N, Z -- Set or cleared according to value. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
lda #Oper |
a9 |
2 |
2 |
Zero Page |
lda Oper |
a5 |
2 |
3 |
Zero Page Indexed X |
lda Oper,x |
b5 |
2 |
4 |
Absolute |
lda OperW |
ad |
3 |
4 |
Absolute Indexed X |
lda OperW,x |
bd |
3 |
4+ |
Absolute Indexed Y |
lda OperW,y |
b9 |
3 |
4+ |
Indexed Indirect |
lda (Oper,x) |
a1 |
2 |
6 |
Indirect Indexed |
lda (Oper),y |
b1 |
2 |
5+ |
+ Add one cycle if page boundary crossed |
Load X Index with memory.
Operation |
M to X |
Flags |
N, Z -- Set or cleared according to value. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
ldx #Oper |
a2 |
2 |
2 |
Zero Page |
ldx Oper |
a6 |
2 |
3 |
Zero Page Indexed Y |
ldx Oper,y |
b6 |
2 |
4 |
Absolute |
ldx OperW |
ae |
3 |
4 |
Absolute Indexed Y |
ldx OperW,y |
be |
3 |
4+ |
+ Add one cycle if page boundary crossed |
Load Y Index with memory.
Operation |
M to Y |
Flags |
N, Z -- Set or cleared according to value. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
ldy #Oper |
a0 |
2 |
2 |
Zero Page |
ldy Oper |
a4 |
2 |
3 |
Zero Page Indexed X |
ldy Oper,x |
b4 |
2 |
4 |
Absolute |
ldy OperW |
ac |
3 |
4 |
Absolute Indexed X |
ldy OperW,x |
bc |
3 |
4+ |
+ Add one cycle if page boundary crossed |
Logical shift right, or shift memory or accumulator right one bit.
This differs from ror
in that a 0 is shifted in.
The effect is division by 2, or by a power of 2 when repeated.
The complementary shift instruction is asl
.
Operation |
bit 0 to C; bits 7--1 to bits 6--0; 0 to bit 7 |
Flags |
N -- Cleared. Z, C -- Set or cleared according to result. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Accumulator |
lsr a |
4a |
1 |
2 |
Zero Page |
lsr Oper |
46 |
2 |
5 |
Zero Page Indexed X |
lsr Oper,x |
56 |
2 |
6 |
Absolute |
lsr OperW |
4e |
3 |
6 |
Absolute Indexed X |
lsr OperW,x |
5e |
3 |
7 |
No operation. Take two cycles and do nothing.
Operation |
Nothing. |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
nop |
ea |
1 |
2 |
Logical OR to the accumulator.
Operation |
A OR M -- Result in A |
Flags |
N, Z -- Set or cleared according to result. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
ora #Oper |
09 |
2 |
2 |
Zero Page |
ora Oper |
05 |
2 |
3 |
Zero Page Indexed X |
ora Oper,x |
15 |
2 |
4 |
Absolute |
ora OperW |
0d |
3 |
4 |
Absolute Indexed X |
ora OperW,x |
1d |
3 |
4+ |
Absolute Indexed Y |
ora OperW,y |
19 |
3 |
4+ |
Indexed Indirect |
ora (Oper,x) |
01 |
2 |
6 |
Indirect Indexed |
ora (Oper),y |
11 |
2 |
5 |
+ Add one cycle if page boundary crossed |
Push accumulator to stack.
Operation |
A -- To stack. S - 1 -- To S. |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
pha |
48 |
1 |
3 |
Push processor flags to stack.
Operation |
P -- To stack. S - 1 -- To S. |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
php |
08 |
1 |
3 |
Pull accumulator from stack.
Other CPU architectures call this "pop."
Operation |
Stack -- To A. S + 1 -- To S. |
Flags |
N, Z -- Set or cleared according to value pulled. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
pla |
68 |
1 |
4 |
Pull processor flags from stack.
Other CPU architectures call this "pop."
Operation |
Stack -- To P. S + 1 -- To S. |
Flags |
N, V, B, D, I, Z, C -- From stack. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
plp |
28 |
1 |
4 |
Rotate memory or accumulator left one bit.
This differs from asl
in that C is shifted in.
Operation |
bit 7 to C; bits 6--0 to bits 7--1; C to bit 0 |
Flags |
N, Z -- Set or cleared according to result. C -- From bit 7. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Accumulator |
rol a |
2a |
1 |
2 |
Zero Page |
rol Oper |
26 |
2 |
5 |
Zero Page Indexed X |
rol Oper,x |
36 |
2 |
6 |
Absolute |
rol OperW |
2e |
3 |
6 |
Absolute Indexed X |
rol OperW,x |
3e |
3 |
7 |
Rotate memory or accumulator right one bit.
This differs from lsr
in that C is shifted in.
This instruction is not available on 6502-series CPUs made before July 1976.
Operation |
bit 0 to C; bits 7--1 to bits 6--0; C to bit 7 |
Flags |
N, Z -- Set or cleared according to result. C -- From bit 0. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Accumulator |
ror a |
6a |
1 |
2 |
Zero Page |
ror Oper |
66 |
2 |
5 |
Zero Page Indexed X |
ror Oper,x |
76 |
2 |
6 |
Absolute |
ror OperW |
6e |
3 |
6 |
Absolute Indexed X |
ror OperW,x |
7e |
3 |
7 |
Return from interrupt.
Operation |
Stack -- To P; S + 1 -- To S; Stack -- To PC; S + 2 -- To S. |
Flags |
N, V, B, D, I, Z, C -- From stack. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
rti |
40 |
1 |
6 |
Return to saved, or return from subroutine.
Operation |
Stack -- To PC; S + 2 -- To S; PC + 1 -- To PC. |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
rts |
60 |
1 |
6 |
Subtract memory from accumulator with carry.
This is the only subtraction instruction; there is no subtraction without carry.
Performs binary subtraction when D = 0; performs binary-coded decimal (BCD) subtraction when D = 1.
The carry is used as a borrow, and its meaning is inverted: 1 is borrowed when C = 0, and 0 is borrowed when C = 1.
The complementary math instruction is adc
.
Operation |
A - M - !C -- Result in A, C |
Flags |
N, V, C, Z -- Set or cleared according to result. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Immediate |
sbc #Oper |
e9 |
2 |
2 |
Zero Page |
sbc Oper |
e5 |
2 |
3 |
Zero Page Indexed X |
sbc Oper,x |
f5 |
2 |
4 |
Absolute |
sbc OperW |
ed |
3 |
4 |
Absolute Indexed X |
sbc OperW,x |
fd |
3 |
4+ |
Absolute Indexed Y |
sbc OperW,y |
f9 |
3 |
4+ |
Indexed Indirect |
sbc (Oper,x) |
e1 |
2 |
6 |
Indirect Indexed |
sbc (Oper),y |
f1 |
2 |
5+ |
+ Add one cycle if page boundary crossed |
Set carry flag.
Operation |
1 to C |
Flags |
C -- Set. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
sec |
38 |
1 |
2 |
Set decimal mode.
After this instruction, adc
and sbc
perform binary-coded decimal (BCD) arithmetic.
Operation |
1 to D |
Flags |
D -- Set. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
sed |
f8 |
1 |
2 |
Set interrupt disable bit.
This instruction disables IRQ; use cli
to enable IRQ.
Operation |
1 to I |
Flags |
I -- Set. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
sei |
78 |
1 |
2 |
Store accumulator in memory.
Operation |
A to M |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Zero Page |
sta Oper |
85 |
2 |
3 |
Zero Page Indexed X |
sta Oper,x |
95 |
2 |
4 |
Absolute |
sta OperW |
8d |
3 |
4 |
Absolute Indexed X |
sta OperW,x |
9d |
3 |
5 |
Absolute Indexed Y |
sta OperW,y |
99 |
3 |
5 |
Indexed Indirect |
sta (Oper,x) |
81 |
2 |
6 |
Indirect Indexed |
sta (Oper),y |
91 |
2 |
6 |
Store X Index in memory.
Operation |
X to M |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Zero Page |
stx Oper |
86 |
2 |
3 |
Zero Page Indexed Y |
stx Oper,y |
96 |
2 |
4 |
Absolute |
stx OperW |
8e |
3 |
4 |
Store Y Index in memory.
Operation |
Y to M |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Zero Page |
sty Oper |
84 |
2 |
3 |
Zero Page Indexed X |
sty Oper,x |
94 |
2 |
4 |
Absolute |
sty OperW |
8c |
3 |
4 |
Transfer accumulator to X Index.
Operation |
A to X |
Flags |
N, Z -- Set or cleared according to value. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
tax |
aa |
1 |
2 |
Transfer accumulator to Y Index.
Operation |
A to Y |
Flags |
N, Z -- Set or cleared according to value. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
tay |
a8 |
1 |
2 |
Transfer stack pointer to X Index.
Operation |
S to X |
Flags |
N, Z -- Set or cleared according to value. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
tsx |
ba |
1 |
2 |
Transfer X Index to accumulator.
Operation |
X to A |
Flags |
N, Z -- Set or cleared according to value. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
txa |
8a |
1 |
2 |
Transfer X Index to stack pointer.
Operation |
X to S |
Flags |
None. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
txs |
9a |
1 |
2 |
Transfer Y Index to accumulator.
Operation |
Y to A |
Flags |
N, Z -- Set or cleared according to value. |
Mode |
Assembly Form |
Hex |
Bytes |
Cycles |
Implied |
tya |
98 |
1 |
2 |