Introduction
The 6502 adds and subtracts 8-bit values with the carry flag, so that longer numbers are done a byte at a time: clear the carry (CLC) before the first ADC, set it (SEC) before the first SBC. There is no multiply or divide. All arithmetic is on the accumulator, apart from increment and decrement, which also work on memory and the index registers.
The instructions
Each form is written mode opcode, bytes, cycles; “+1 page” is one more cycle when an index crosses a page boundary.
| Instruction | Forms | What it does | Flags |
|---|---|---|---|
adc | imm 69, 2, 2zp 65, 2, 3zp,X 75, 2, 4abs 6D, 3, 4abs,X 7D, 3, 4 +1 pageabs,Y 79, 3, 4 +1 page(zp,X) 61, 2, 6(zp),Y 71, 2, 5 +1 page(zp) 72, 2, 5 (65C02) | A = A + memory + C. See decimal mode. | N V Z C |
sbc | imm E9, 2, 2zp E5, 2, 3zp,X F5, 2, 4abs ED, 3, 4abs,X FD, 3, 4 +1 pageabs,Y F9, 3, 4 +1 page(zp,X) E1, 2, 6(zp),Y F1, 2, 5 +1 page(zp) F2, 2, 5 (65C02) | A = A − memory − (1 − C): the carry is the inverse of the borrow. The opcode EB is an undocumented copy of immediate SBC. | N V Z C |
inc | zp E6, 2, 5zp,X F6, 2, 6abs EE, 3, 6abs,X FE, 3, 7A 1A, 1, 2 (65C02) | Adds one to memory (or, on the 65C02, to the accumulator). The carry is not used or changed. | N Z |
dec | zp C6, 2, 5zp,X D6, 2, 6abs CE, 3, 6abs,X DE, 3, 7A 3A, 1, 2 (65C02) | Subtracts one from memory (or, on the 65C02, from the accumulator). | N Z |
inx | implied E8, 1, 2 | X = X + 1. | N Z |
iny | implied C8, 1, 2 | Y = Y + 1. | N Z |
dex | implied CA, 1, 2 | X = X − 1. | N Z |
dey | implied 88, 1, 2 | Y = Y − 1. | N Z |
cmp | imm C9, 2, 2zp C5, 2, 3zp,X D5, 2, 4abs CD, 3, 4abs,X DD, 3, 4 +1 pageabs,Y D9, 3, 4 +1 page(zp,X) C1, 2, 6(zp),Y D1, 2, 5 +1 page(zp) D2, 2, 5 (65C02) | Compares A with memory by subtracting it without storing the result. C is set when A ≥ memory (unsigned), Z when they are equal. | N Z C |
cpx | imm E0, 2, 2zp E4, 2, 3abs EC, 3, 4 | Compares X with memory. | N Z C |
cpy | imm C0, 2, 2zp C4, 2, 3abs CC, 3, 4 | Compares Y with memory. | N Z C |
Decimal mode
When the D flag is set (SED), ADC and SBC treat each byte as two binary-coded decimal digits:
$19 + $01 gives $20. This works on the NMOS 6502, the 6510 and the
65C02. It does not work on the NES’s 2A03 and 2A07, where D can be set but
ADC and SBC always add in binary.
On the NMOS chip, N, V and Z after a decimal ADC or SBC are not meaningful (only C is a reliable result flag), and the chip does not clear D when it takes an interrupt, so an interrupt handler must start with CLD. The 65C02 sets N, V and Z correctly from the decimal result, takes one more cycle in decimal mode, and clears D on an interrupt.
Notes
- Overflow. V is set when two numbers of the same sign give a result of the other sign, for signed arithmetic. There is no instruction to set V; CLV clears it, and the BVS and BVC branches test it.
- Memory increments are read-modify-write: the NMOS chip writes the unchanged byte back, then the changed one. This matters when the address is a hardware register.