HALICERY

free-time coding, hardware dev, articles

Top
Home 8042 Blogs About
Home IntelEssential ALU Investigations IntelEssential_ALU

Last modified: Sun Jun 14 12:37:34 UTC+0200 2026 © A. Tarpai


ADDITION AND SUBTRACTION WITH THE ADDER

The Adder

[toc]

The 1-bit adder's combinational logic outputs a result- and a carry out bit based on input of two operand- and the carry in bit. The 2-bit output thus is the sum as a binary value, where carry out is the higher order bit: A + B + C = C' Y.

It's a relatively simple digital circuit with a truth table of:

1-bit adder circuit

      in in
      _|_|_
     | A B |               A     0   0   0   0   1   1   1   1
     |    C|_ in           B     0   0   1   1   0   0   1   1
out _|C'   |               C     0   1   0   1   0   1   0   1
     |__Y__|            _______________________________________
        |               C' Y    00  01  01  10  01  10  10  11
       out

Connecting multiple 1-bit adders sequentially can perform addition of N-bits. This is a 4-bit ripple-carry adder as it was used by the Intel 4004. We are in 1971.

4-bit adder with ripple-carry

                bit3      bit3      bit1      bit0

                 •---------•---------•---------•----------  A[3..0] in
                 | •-------|-•-------|-•-------|-•--------  B[3..0] in
                _|_|_     _|_|_     _|_|_     _|_|_
               | A B |   | A B |   | A B |   | A B |
               |    C|_  |    C|_  |    C|_  |    C|_______CARRY in______
 __CARRY out___|C'   | \_|C'   | \_|C'   | \_|C'   |                     |
|              |__Y__|   |__Y__|   |__Y__|   |__Y__|                     |
|                 |         |         |         |                        |
|                 •---------•---------•---------•---------  Y[3..0] out  |
|                                                                        |
|                   ____                                                 |
|__________________| CF |________________________________________________|
                   |____|

Carryin and carryout is the same flip-flop, the Carry Flag (CF). It is implemented for multi-digit additions and to signal overflow. It is also the output of that last adder, after adding the msb at the end of the addition–sequence.

This 4-bit adder is used mostly for analysis and for the the examples. But the principle is the same on 8-, 16- or wider bit size.

Addition of binary numbers

Terms: ADDEND + ADDENDUM = SUM (addendum is my term to differentiate between the two)

A 4-bit adder can be used to add binary numbers in the range of 0–15. It signals overflow with the carry bit set to one.

F. ex. adding 5 to 9 the result fits into 4-bits and the carry bit is cleared; while adding 10 to 9 will overflow and the carry bit is set. Columnar addition without intermediate carry:

           1 0 0 1   9                         1 0 0 1   9
      +    0 1 0 1   5                    +    1 0 1 1   10
           _______                             _______
carry = 0 |1 1 1 0   14             carry = 1 |0 0 1 1   3
        __|                                 __|

                                          overflow

Interpreting overflow

Overflow is not an error: the result is somewhat correct as if carry is an extension, the highest order bit of the result does not fit into 4-bits. The overflow gets carried into the carry bit:

                1 0 0 1   9
           +    1 0 1 1   10
                _______
     carry = 1 |0 0 1 1   16 + 3 = 19
             __|

Carry can be used to interpret the correct sum, as decimal 19 above by using carry with a value of 24 = 16. See BCD instructions how this was done in the early days.

The above 9 + 10 = 19 also shows as if addition wraps around in the adder:

The adder never overflows

Generally, an N-bit adder with carry has 2 × 2N = 2N+1 output states. It counts from 0 to 2N+1–1.

Considering carry as the Nth bit of the result, the sum is N+1 bits wide, numbers doubled in range. A 4-bit adder produces sum in the 0–31 range:

The A + B + CY sum in a 4-bit adder will be then 5-bits: A + B + CY always fit:

4-bit adder sum on 5 bits

Carry in multi-digit additions

§I was doing some readings about the 4004 microprocessor, which was made for BCD-digit calculations. The multi-digit term was used there. §

For multi-digit additions the carry is used in the following way. Carry is initially cleared. First add the low-order 4-bit, then add the next and so on. The carry bit takes care of overflow in each step, i.e. the adder adds one more when carry is set by the previous addition. This is similar to the columnar addition method on paper.

F. ex. adding two 16-bit numbers with a 4-bit adder:

                    1_      0_      1_      0__ Carry in = 0
   2E83             2 \     E \     8 \     3
 + A70F        +    A  \    7  \    0  \    F
 = D592        =  0 D   \_1 5   \_0 9   \_1 2
                  |
                 Carry out

After these additions carry = 0, meaning no overflow has occurred. The result fits into 16-bit.

Addition semantics

Additions with carry set

A set carry before addition will add one more to the sum. Therefore, e.g. adding 4 and CY=1 or 5 and CY=0 will produce equivalent results. The adder transforms into the same output state and the semantic of both input combinations is "ADD 5". The only difference is intermediate carry bits – which will have significance for signed interpretation only. For (unsigned) additions these results are identical:

§ Addition semantics of the 4-bit adder §

Add 2N semantics and carry-propagation

The most notable is the last addition, all ones with carry. It can occur in multi-digit additions after overflow in the previous addition.

In multi-digit addition the semantics is add 2N. E.g. on 4-bits, although the value 16 is not a valid 4-bit number, its semantics is plus 16, because this is how in a multi-digit addition can be interpreted.

                    1_      1_      1_      0__ Carry in = 0
   2E86             2 \     E \     8 \     6
 + A7FE        +    A  \    7  \    F  \    E
 = D682        =  0 D   \_1 6   \_1 8   \_1 4
                  |                 |
                 Carry out          |
                                 8 + F + 1 = 18h
                                 "add 16"

                              <------------
                            carry-propagation

For the second digit (8), the addition leaves the same value in the adder and carry is preserved. It is propagated, so the next addition will add one more. Adding all ones with carry serves the purpose of carry-propagation.

Adding all ones with carry = 1 is similar to adding all zero with carry = 0 in that it does not change the state of the adder:

§ The two additions that do not change the state of the adder §


Subtracting with the adder

§ Terms: MINUEND - SUBTRAHEND = DIFFERENCE §

Early ALU-s contained one adder circuitry only – to save component space on chip. The adder can be fully used for subtraction and for building the SUB instruction logic upon. Why is this possible and how exactly working is the rest of this text is about.

Addition as subtraction

It is possible to use the adder for subtraction based on how additions wrap-around within the whole addition range.

If we ignore carry for a while, subtracting 7 from 10 is equivalent to adding the value of 9 to 10 in a 4-bit adder:

In other words, certain additions can be interpreted as subtraction. By adding the value of 9 to the minuend in this case, the adder performed apparent subtraction i.e. computed the difference between two binary numbers.

There are two different state change possibilities for "ADD 9" in the adder, to move from 10 to 3:

                         Two's complement            One's complement
                         of 7 is 9                   of 7 is 8

   Subtraction           Perform addition            Perform addition

                                  0    CY                     1    CY
   1010  = 10               1 0 1 0    10               1 0 1 0    10
-  0111  = 7             +  1 0 0 1     9            +  1 0 0 0     8
_______                     _______                     _______
   0011  = 3             1 |0 0 1 1     3            1 |0 0 1 1     3
                        ___|                        ___|
                     Carry set                    Carry set

The results are indeed identical.

The first method will lead us to storage and representation of signed numbers. Mathematically, subtracting 7 is equivalent to adding −7. In this sense 9 can represent −7 as a stored signed number (on 4-bits). Signed two's complement arithmetic is another chapter.

The second method will lead us to the subtraction algorithm and how the SUB instruction can be implemented in hardware using the adder.

About one's complement

One's complement – or simply complement – is a logical operation, inversion of each bits and can be implemented cheap by inverters (NOT-gates). For example, the one's complement value of 3 is 12 on 4-bits:

Implementing one's complement: logical NOT instruction

    +-----+-----+-----+-----+
    |  0  |  0  |  1  |  1  |     3
    +-----+-----+-----+-----+
       |     |     |     |
      NOT   NOT   NOT   NOT
       |     |     |     |
    +-----+-----+-----+-----+
    |  1  |  1  |  0  |  0  |    12
    +-----+-----+-----+-----+

          0011           0011                    0011
     AND  1100      XOR  1100                 +  1100
     _________      _________               _________
       =  0000        =  1111                 =  1111

One's complement pairs have the following properties:

About two's complement

In the example above, 9 is the two's complement value of 7 (on 4 bits). Each binary number has a matching two's complement value.

The following is always true for two's complement pairs:

We can see the symmetry for these two values:

To compute the two's complement value of a binary number the following rules are applied:

The operation is reversible. E.g. 7 → 9 → 7. Two's complement values are arranged in unique pairs:

Note that "add one and complement" does NOT WORK. E.g. 4:

    0100 = 4                           0100 = 4
    1011 = 11 complement               0101 = 5  add one
    1100 = 12 add one                  1010 = 10 complement

    correct                            WRONG!

Subtracting by two's complement

To subtract an arbitrary number B from A using two's complement is a two-step process. First the two's complement of B has to be computed, then this value added to A. The detailed steps using the adder are the following:

complement B
carry = 0
add 1 to B

carry = 0
add B to A

Since even the Intel 4004 in 1971 had the SUB instruction, this is hypothetical, but good to remember that every addition is also a subtraction by interpretation – and vica versa.

E.g. adding FFh in a byte adder leaves the result one less to the original value.

Two's complement is not suitable to implement a subtraction algorithm, mainly because of how subtracting zero is represented. It can be used to subtract constants, but the most important use is to interpret results after subtraction as it is a form of negation.

Subtracting by complement

One problem is that two's complementing is an arithmetic operation and involves the adder (add one). The solution is, since the two's complement value will be used in a subsequent addition, a set carry bit can be used to add one.

complement B
carry = 1
add B to A

Thus, subtraction becomes a sequence of bit inversion and addition:

It is not even simpler, but there is a very important property difference in how zero is subtracted by these two methods.

One's complement is real complement, the sum of each pair is a constant value. If we include carry as well, it's a perfect arithmetic complement to zero by addition:

Two's complement does not differentiate between zero and two's complement zero:

Interpreting underflow

When using the adder for subtraction we quickly slip into uncharted territory: negative numbers.

What happens when the subtrahend is bigger that the minuend? Let's perform subtraction of 3 - 14 in our 4-bit adder via the complement and set carry method:

3 - 14 = -11               1  = carry set
                        0011  = 3
                    +   0001  = 1 (complement of 14)
                    = 0 0101  = 5
                      |
                     Carry cleared

Mathematically the result is negative and equals to −11. We got 5 in the adder. Carry = 0 means an underflow has occurred. We must interpret this in code and act, accordingly, e.g. print out the result with a negative sign "−" before the number.

But what is number 5? It is actually the two's complement value of 11:

 5 =   0101
              invert bits
10 =   1010
              add one
11 =   1011

This means that our 4-bit adder can subtract numbers in the range of 0–15. It needs a little bit of work. Interpreting the Carry bit after these additions correctly, the program can deal with negative results in the full range of −15 – 15:

Generally, for an N-bit adder this interpretation range is ± 2N-1.

This interpretation is the origin of signed two's complement representation: below zero comes −1, then −2 etc.

Opposite carry meaning

When an addition is interpreted as subtraction, carry operates the opposite way to signal overflow – more precisely underflow. To get a smaller result, carry = 1 is supposed to be set and it means no underflow has occurred. The carry bit has a different meaning, and it is opposite from addition (the adder operation unchanged!):

Multi-digit subtraction in the adder

A multi-digit subtraction with the adder is performed the following way: set carry before adding the first complement, add the next complement etc. The carry bit takes care of underflow in each step, i.e. the adder adds one less, when CY left cleared by the previous addition – thus apparently subtract one more from the next digit. At the end interpret carry the opposite way: a cleared carry flag means underflow.

Example: a 16-bit subtraction to compute 8436 - 2584 = 5852 decimal (20F4h - A18h = 16DCh) with an adder, showing both 4- and 8-bit versions. Complement of 0A18h is F5E7h.

16-bit sub       16-bit ADDER     2 × 8-bit ADDER       4 × 4-bit ADDER

                      1__            1_       1__         0_      1_      0_      1__ Carry in
   20F4            20F4             20 \     F4           2 \     0 \     F \     4
 - 0A18        +   F5E7         +   F5  \    E7       +   F  \    5  \    E  \    7
 = 16DC          1 16DC           1 16   \_1 DC         1 1   \_0 6   \_1 D   \_0 C
                 |                |                     |
                Carry out        Carry out             Carry out

After these additions carry is set – meaning no underflow occurred and the result is a correct positive value.

Another interesting observation is that it does not matter what granularity the subtraction is computed. 4-, 8- or 16 bits, the results are identical. A 4-bit adder's carry out is just an intermediate carry for the 8-bit adder etc. What matters is the last carry (and that the first carry was set).

Subtraction semantics

Subtractions with carry cleared

It can be seen in multi-digit subtraction, that a cleared carry before addition interpreted as subtraction will add one less to the result, thus the adder apparently subtracts one more.

Adding one less will subtract one more

The semantic of additions interpreted as subtractions is similar to additions. E.g. add 4 with CY=1 is equivalent to adding 5 with CY=0 in the adder and both will have the "SUB 11" semantics. The only difference is intermediate carry bits – which will have significance for signed interpretation only. As for unsigned subtractions these results are identical.

This table shows all possible additions on 4-bit, interpreted as subtraction. These are the subtraction semantics of these additions:

The most notable is how subtract zero is performed by the complement method (add all one's with carry). The other peculiar subtraction is 16 (or 2N in an N-bit adder generally).

Subtract zero by Negative Zero

When subtracting zero with the complement rule, the corresponding addition is all one's with carry. Let's call this value negative zero to distinguish it from the all zero addition.

Addition of negative zero will leave the same result in the adder and will certainly set CY. Thus, signaling no underflow has occurred after subtraction:

Adding the two's complement of 0 = 0 will not set CY.

Subtract 2N semantics

The interpretation is similar to the add 2N case. It can occur in multi-digit subtraction after underflow in the previous subtraction, when the complement of the subtrahend is zero (subtract 15 or 2N-1 with underflow).

In a 4-bit adder, therefore, the semantic is subtract 15 + 1 = 16. As an example, the multi-digit subtraction of 4A3h - 2FEh = 1A5h. Complement of 2FEh is D01h. For the middle digit the adder performs an addition of 0 with carry = 0:

"-16" semantics in 4A3 + D01 + 1 = 1 1A5

        1                  0_      0_      1__ Carry in = 1
    4 A 3                  4 \     A \     3
  + D 0 1             +    D  \    0  \    1
 _________            =  1 1   \_0 A   \_0 5
  1 1 A 5                |
                  Carry out        |
               No underflow      A + 0 + 0 = A
                                 "sub 16"

                              <------------
                             borrow-propagation

Borrow-propagation

All zero in addition interpreted as subtraction serves the purpose of borrow-propagation: borrow is preserved without changing the adder state, so the next digit addition will subtract one more.

Binary subtraction

The concept of BORROW

The term borrow comes from manual subtraction, somewhat similar to carry but it means one minus during the columnar method. For a subsequent operation the meaning of carry is add one more – the meaning of borrow is subtract one more.

An example decimal subtraction with pen and paper (without going into negatives now):

      carry                    borrow

     +1 <--                   -1 -->
      5     4                  5     4
  +   3     8              -   3     8
 _____________            _____________
      9     2                  1     6


  54 + 38 = 92            54 - 38 = 16

We started with no borrow for the first one, but that borrowed. The second subtracted with borrow, but did not borrow. We can start to see a subtract algorithm with the borrow bit, BW ← SUB ← BW:

A theoretical "SUBBER" circuit

We could – but no-one does – construct a separate binary subber circuit. The subber would subtract the subtrahend (B) with a borrow-bit (BW) from the minuend (A) – and outputs the result and a borrow-bit: A - B - BW = BW' Y.

               B
           ____|____            Y = A - B - BW
          |    A    |
          |         |
    BW ___|  SUBBER |__ BW
    out   |____ ____|   in
               |
               Y

Based on the BORROW concept, a set BW-bit before subtraction would make the subber subtract one more. After subtraction, an underflow sets the BW bit – so the next subtraction subtracts one more.

To start with the 1-bit "SUBBER" combinational logic, the idea is if a 1-bit adder adds to a 0 or 1 bit, a corresponding "subber" would subtract from 0 or 1:
>Subtract 0 from 1 should produce a one bit (1-0=1), Subtract 1 from 1 should produce a zero bit (1-1=0) etc. But subtract 1 from 0 should produce a one bit (0-1=1) and set the bit signaling underflow. The output is 11, this will be the −1 interpretation. Consequently, subtract 1 and borrow from 0 results in 10. That is −2.

           add with carry

         ----------------->
10   11 | 00   01 | 10   11
<-----------------
-2   -1
subtract with borrow

As if a subber's 2-bit output (result bit and BW bit) counts in the opposite direction from the adder:

We can compile a 1-bit subber's truth table:

1-bit subber's truth table:

        A       0   0   0   0   1   1   1   1
     -  B       0   0   1   1   0   0   1   1
     - BW       0   1   0   1   0   1   0   1
   _______    ________________________________
    BW' Y      00  11  11  10  01  00  00  11

Interpretation:

                0   0   0   0   1   1   1   1
               -0  -1  -1  -2  -0  -1  -1  -2
            =   0  -1  -1  -2   1   0   0  -1

An N-bit subber with ripple-borrow would be very similar to the adder, only the combinational logic function is different.

Subber vs. adder comparison

Lets perform a 3-digit subtraction 1187 - 766 = 421 using a 4-bit adder- and subber and compare the operation. This is hex 4A3h - 2FEh.

For the subber:

For the adder:

With an 4-bit subber
                                 2        F        E
                            _____|________|________|_____
        4 A 3              |     4        A        3     |
  -     2 F E              |     1 __     1 __     0 __  |
  -         0           0 _|__ 0 1   \_ 1 A   \_ 1 5   \_|_ 0 (borrow)
______________             |_____|________|________|_____|
  =   0 1 A 5                    |        |        |
                                 1        A        5


With an 4-bit adder
                                 D        0        1
                            _____|________|________|_____
        4 A 3              |     4        A        3     |
  +     D 0 1              |     0 __     0 __     1 __  |
  +         1           1 _|__ 1 1   \_ 0 A   \_ 0 5   \_|_ 1 (carry)
______________             |_____|________|________|_____|
  =   1 1 A 5                    |        |        |
                                 1        A        5

The results are identical, 1A5h = 421:

Interestingly, not only is the output carry bit opposite at the end of the addition sequence, but each intermediate carry bit is also opposite from the subber.

Now when we look at and analyze e.g. the first lsb operation isolated:

                                    _
         E                          E
     ____|____                  ____|____
    |    3    |                |    3    |
    |    0 _  |             _  |    1 _  |  _
 1 _|_ 1 5  \_|_ 0          0 _|_ 0 5  \_|_ 0
    |____|____|                |____|____|
         |                          |
         5                          5

       subber                     adder

It seems like subber operation can be substituted by the adder operation by feeding inverted operands and inverting output carry. The output result in this way will be identical.

But we need proof..

Adder equations: proving subtraction in the adder

This is an attempt to prove that a theoretical subber, which subtracts binary values with borrow and generates a borrow bit can be fully emulated with the adder by adding negated operands and addition.

For an N-bit adder let M = 2N.

The N-bit subber equation for difference is:

D = a − b − c

and the adder equation for sum is:

S = a + b + c

where a and b are non-negative integers (a < M, b < M), c is the overflow/underflow bit (carry/borrow), zero or one. We consider carry as bit-extension of the result, thus max(S) = 2N+1-1 or max(S) < 2M.

The N-bit binary adder performs apparent subtraction by adding the complement of its operands (denoted by overline),

where

b = M−1 − b, and
c = 1 − c

then

S = a + b + c = a + M−1 − b + 1 − c = a − b − c + M = D + M

S = D + M means the result sum is M greater than the difference.

This is exactly the congruence modulo relationship between D and S (S = k M + D). The value left in the adder is D difference.

For output carry, it is cleared when S < M:

a + b + c < M
a + M-1 – b + 1 – c < M
a - b - c < 0
D < 0

i.e. carry is cleared, when the Δ difference is negative. Consequently, carry is set when D >= 0. Here we have proven carryout is opposite borrowout.

These two circuits therefore are interchangeable:

                                                     _
               B                                     B
           ____|____                             ____|____
          |    A    |                           |    A    |
          |         |                     __    |         |   __
    BW ___|  SUBBER |__ BW                CY ___|  ADDER  |__ CY
    out   |____ ____|   in                out   |____ ____|   in
               |                                     |
               Y                                     Y

Interpreting adder-subtraction

If S = D + M then D = S − M, i.e. the mathematical difference is M less, than the sum in the adder. Based on D = S − M there are three types of relationships between the difference D and sum S in the adder:

Math Δ               Value
difference           in adder

negative     D<0     S<M
zero         D=0     S=M
positive     D>0     S>M

Illustrating this relationship between D and S on 4-bits, considering CY as the 5th bit of the addition:

This also proves how unsigned comparison will work correctly with this method in hardware. CMP is subtraction, testing the result

When the Δ difference is negative, S < M. But what is S, the value in the adder? The positive number in the adder is −D = −(S−M) = M − S, which is the two's complement definition (no need for modulo: 0 < S < M).

Adder subtraction examples on 4 bits

In any case, to subtract b+c from a, the addition is a + (M - b - c).

Difference is positive

For 10 − 7 = 3, the Δ difference is positive. The addition is 10 + 7 + 0 = 10 + 8 + 1 = 19 and carry set:

Difference is negative

For 3 − 7 = −4, the Δ difference is negative. The addition is 3 + 7 + 0 = 3 + 8 + 1 = 12 and carry cleared: two's complement of 12 = 4. Or -D = M - S = 16 - 12 = 4. The result should be interpreted as −4:

Implementing the SUB instruction

A desired SUB instruction would subtract binary numbers with a borrow bit – and signal underflow with the same borrow bit set to one in case of underflow (which represents negative results). As if there was a separate subber circuit along with a borrow-flag in the CPU.

The program could simply use e.g. "SUB 7", clear/set- and interpret the borrow bit. The CPU, when it encounters opcode SUB and the value of 7 in the instruction stream, would operate similar to the ADD instruction.

We know by now, that

i.e. there is no need for a separate subber circuit, the already existing adder circuit can implement the SUB instruction in hardware. This is also firmly supported by the Adder equations.

SUB instruction in hardware

Building the SUB instruction logic on top of already present ADD instruction involves only additional bit-inversions (NOT gates). In early processors therefore, fewer circuits were required to perform subtraction. The ADD instruction with carry is the adder operation itself:

SUB instruction in hardware

         +-----------------------------------------------------+
         |SUB                                                  |
         |            +---------------------------+            |
         |            | ADD                       |            |
         |   _____    |        ___________        |    _____   |
   CY <--|--| NOT |<--| CY <--|           |<-- CY |<--| NOT |--|<-- CY
(BORROW) |  |_____|   |       |           |       |   |_____|  |   (BORROW)
         |            |       |   ADDER   |       |    _____   |
         |            |       |           |<-- OP |<--| NOT |--|<-- OP
         |            |       |___________|       |   |_____|  |
         |            |                           |            |
         |            +---------------------------+            |
         |                                                     |
         +-----------------------------------------------------+

This SUB logic:

Redefinition of the carry bit to borrow exists purely for the convenience. By redefining the carry bit, SUB becomes similar how ADD is used by the programmer:

Fun fact: the Intel 4004 SUB

The Intel 4004 SUB logic did not complement carry after the operation. It subtracted with borrow but did not produce borrow. Therefore, for multi-digit subtractions, a CMC (complement carry) instruction had to be inserted before each subsequent SUB. This was corrected in 8008 and later.

Intel x86 ADD/SUB and ADC/SBB instructions

Already in 1972, the Intel 8008 implemented different ADC/SBB and ADD/SUB instructions with or without carry. The meaning of carry was also proper BORROW after subtraction: "An underflow (borrow) sets the carry flip-flop" – 8008 Data Sheet 1978. That means internally, subtraction instructions automatically complemented the carry bit before and after adding complement of the operand.

Intel x86 ADD/SUB is only a convenient instruction support for the first addition/subtraction, automatically clearing Carry/Borrow before the operation. For multi-digit operations, subsequent instructions should not alter and consider Carry/Borrow by using ADC/SBB.

If there exists an adder circuit with carry bit, it's perfectly possible to subtract with the CPU using carry manipulation-, complement- and ADD instructions. The adder uses carry, so the basic instruction for x86 is ADC: add with carry. The other instructions operate as if the following logic is built on top of ADC:

      ADD             SUB             SBB

  +---------+     +---------+     +---------+
  |   CLC   |     |   STC   |     |   CMC   |
  |         |     |  NOT B  |     |  NOT B  |
  +---------+     +---------+     +---------+
  |         |     |         |     |         |
  |   ADC   |     |   ADC   |     |   ADC   |
  |         |     |         |     |         |
  +---------+     +---------+     +---------+
                  |   CMC   |     |   CMC   |
                  +---------+     +---------+


ADC = Add With Carry
SBB = Subtract With Borrow
SUB = Subtract
ADD = Add
CLC = Clear Carry Bit
STC = Set Carry Bit
CMC = Complement Carry Bit

As an example, subtracting 1301h − 0503h = 0DFEh using ADC only.

On 16-bit, these are all equivalent: AX = 0DFEh and CF=0 (no borrow)

16-bit subtraction

mov ax, 0x1301
mov bx, 0x0503
sub ax, bx

mov ax, 0x1301
mov bx, 0x0503
clc  -----------+
sbb ax, bx      | 16-bit SUB implementation with SBB

mov ax, 0x1301
mov bx, 0x0503
stc  -----------+
not bx          |
adc ax, bx      | 16-bit SUB implementation with ADC
cmc ------------+

8-bit multi-digit subtractions (pretend ALU is 8-bits). These are all equivalent:

mov al, 0x01
mov bl, 0x03
sub al, bl        ; AL=FE CF=1 (borrow)
mov al, 0x13
mov bl, 0x05
sbb al, bl        ; AL=0D CF=0 (no borrow)


mov al, 0x01
mov bl, 0x03
stc ------------+
not bl          | SUB implementation with ADC
adc al, bl      |
cmc ------------+ AL=FE CF=1 (borrow)
mov al, 0x13
mov bl, 0x05
cmc ------------+
not bl          | SBB implementation with ADC
adc al, bl      |
cmc ------------+ AL=0D CF=0 (no borrow)


8-bit old-school multi-digit subtraction with ADC
(stc.. adc.. adc.. cmc)

mov al, 0x01
mov bl, 0x03
stc
not bl
adc al, bl        ; AL=FE CF=0
mov al, 0x13
mov bl, 0x05
not bl
adc al, bl
cmc               ; AL=0D CF=0 (no borrow)