ADC
ADC (short for "ADd with Carry") is the mnemonic for a machine language instruction which adds the byte held in the accumulator with that held in the memory address specified: The state of the carry flag before the addition takes place, is taken as the incoming carry in the addition. After the addition, the carry flag will hold the outgoing carry. Contrary to many other CPUs, the architecture of the 65xx family (of which the 6510 in the Commodore 64 is a member) does not have separate instructions for addition with or without taking the carry flag as the incoming carry. Therefore the programmer must make sure that carry is clear prior to an addition for which there is no incoming carry – this is usually accomplished with the CLC instruction, for example:
LDA Num1 Read the first byte value from Num1 CLC No incoming carry; make sure carry is clear ADC Num2 Perform the addition STA Result Store result in Result
This example takes the byte stored in a memory address labelled Num1
, and adds it with the contents of a memory address labelled Num2
, and stores the result in a third place with the label Result
.
There two operational modes for ADC depending on the decimal flag. If this flag is set the operation uses BCD semantics. In addition the zero flag, negative flag and overflow flag usually set accordingly are remain undefined in this mode.
In a few special cases (such as immediately following a BCS), the carry is always clear in any situation where the CPU reaches the ADC instruction; this allows for leaving out the CLC, saving 1 byte and 2 machine cycles execution time.
The inclusion of the incoming carry provides a simple means to add binary integers of arbitrary length, "spread" across two or more bytes: Add the least significant byte pair first with the carry cleared, then add increasingly significant bytes without modifying the carry. This will let the outgoing carry from one addition "travel" from one addition to the next. The following example assumes that Num1
and Num2
mark the first of two series of bytes, of increasing significance, each holding a "dozens-of-bits" integer, and stores the result as a series of byte in the same order, beginning at label Result
:
LDA Num1 Add the least CLC significant pair ADC Num2 with the carry STA Result cleared ... LDA Num1+1 Add next byte ADC Num2+1 pair without STA Result+1 clearing carry LDA Num1+2 and the next ADC Num2+2 pair... STA Result+2 ... etc.
ADC handles both signed and unsigned integers: Both examples above will yield correct results for any pair of integer where both the integers and the resulting sum are within the limits imposed by the number of bits involved: The single-byte addition example works for unsigned integers in the range 0–255/$0–FF as well as signed integers in the −128–+127/$−80–+7F range. For 16-bit (2 bytes) unsigned integers, the limits are 0–65535/$0–FFFF; for signed 16-bit quantities, it's −32768–+32767/$−8000–+7FFF, etc.
Addressing modes[edit | edit source]
Opcode | Addressing mode |
Assembler format |
Length in bytes |
Number of cycles | |
Dec | Hex | ||||
105 | 69 | Immediate | ADC #nn | 2 | 2 |
109 | 6D | Absolute | ADC nnnn | 3 | 4 |
125 | 7D | Absolute,X | ADC nnnn,X | 3 | 4* |
121 | 79 | Absolute,Y | ADC nnnn,Y | 3 | 4* |
101 | 65 | Zeropage | ADC nn | 2 | 3 |
117 | 75 | Zeropage,X | ADC nn,X | 2 | 4* |
97 | 61 | Indexed-indirect | ADC (nn,X) | 2 | 6 |
113 | 71 | Indirect-indexed | ADC (nn),Y | 2 | 5* |
ADC supports eight different addressing modes, as shown in the table at right.
In the assembler formats listed, nn represents a single-byte (8-bit) figure, and nnnn is a two-byte (16-bit) address.
With some addressing forms (marked with an asterisk, *, in the "Number of cycles" column) the execution time for ADC depends on the circumstances: In cases where the indexing requires the CPU to "reach across" a page boundary from the base address, the execution time is 1 cycle longer than listed here.
CPU flags[edit | edit source]
ADC affects 4 of the CPU's status flags:
- The negative flag is set if the result is negative, i.e. has it's most significant bit set (not in decimal mode).
- The overflow flag is set if the operation results in an overflow (not in decimal mode).
- The zero flag is set if the result is zero, or cleared if it is non-zero (not in decimal mode).
- The carry flag is set if the addition resulted in an outgoing carry.
Examples[edit | edit source]
Reverse subtraction
Using SBC, a value can be subtracted from A, but there's no direct way to subtract A from some value. Other CPU's instruction sets like the one for the ARM architecture includes instructions RSB (reverse subtract) and RSC (reverse subtract with carry) that negate the register and add the value. The 6510 can do this too:
; A = Value - A EOR #$FF SEC ADC Value
The value in A is negated by calculating the two's complement (one's complate and adding one) resulting in (−A + Value).