ADC

From C64-Wiki
Jump to navigationJump to search

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).