# Negative numbers and subtraction

*Two's complement, and one block that does both*

Two's complement encodes negative numbers so the same adder can subtract: to compute A minus B, add A to the bitwise-inverted B with a carry-in of 1. Adding one XOR gate per bit turns a plain adder into a combined adder/subtractor.

Group: Processor
URL: https://digiwleea.wleeaf.dev/learn/subtract/

The [8-bit adder](https://digiwleea.wleeaf.dev/learn/adder8/) adds. To get subtraction we could design a whole separate borrow circuit, but there is a far nicer route: represent negative numbers in **two's complement**, and subtraction becomes addition with two tiny tweaks. The same eight [full adders](https://digiwleea.wleeaf.dev/learn/fulladder/) then do both jobs, steered by a single control bit.

## Two's complement: how negatives fit on the same wires

With 8 wires you have 256 bit patterns. Two's complement spends half of them on negatives: patterns with the top bit `0` are `0` to `127` as usual, and patterns with the top bit `1` stand for `-128` to `-1`. The rule to negate a number is: **flip every bit, then add 1**. So `+1` is `0000 0001`; flip to `1111 1110`, add 1 to get `1111 1111`, which is `-1`. The beauty is that ordinary binary addition then just works across the sign: `1 + (-1)` adds `0000 0001 + 1111 1111` and the carry falls off the top, leaving `0000 0000`.

> **KEY:** Why "flip and add 1" works: flipping all bits gives `255 - B` (the **ones' complement**). Adding 1 makes `256 - B`. In 8-bit arithmetic the `256` wraps to `0`, so `A + (256 - B)` lands on `A - B`. Subtraction is addition of the negation, and the negation is just inversion plus a carry-in of 1.

## Turning the adder into an adder/subtractor

Here is the trick. Put one [XOR](https://digiwleea.wleeaf.dev/learn/xor/) gate on each `B` wire before it enters the adder, and feed a shared control line `SUB` to the other input of every XOR. Recall from the [XOR](https://digiwleea.wleeaf.dev/learn/xor/) lesson that `X XOR 0 = X` and `X XOR 1 = NOT X`: the XOR is a **controllable inverter**. When `SUB = 0` the `B` bits pass through unchanged and you get `A + B`. When `SUB = 1` every `B` bit is flipped, and if you also feed that same `SUB` into the adder's carry-in (the `+1`), the adder computes `A + (NOT B) + 1 = A - B`.

1. Take the [8-bit adder](https://digiwleea.wleeaf.dev/learn/adder8/) you built.
2. On each `Bi` wire, insert an [XOR](https://digiwleea.wleeaf.dev/learn/xor/): one input is `Bi`, the other is the shared `SUB` line. The XOR output feeds the adder.
3. Wire `SUB` into the adder's carry-in `CIN` as well (that supplies the `+1`).
4. `SUB = 0` gives `A + B`; `SUB = 1` gives `A - B`. One control bit picks the operation.

**Q (Try it):** Negate `+6` by hand using two's complement (flip every bit, then add 1), starting from `0000 0110`. Then check: add your result to `+6` and confirm you get zero.

**A:** Flip `0000 0110` to `1111 1001`, then add 1: `1111 1010`, which is `-6`. Check by adding to `+6`: `0000 0110 + 1111 1010 = 1 0000 0000`. The carry falls off the top of the 8 bits, leaving `0000 0000`, exactly zero. That is why `+6` and its two's complement cancel.

_Circuit diagram: An 8-bit adder/subtractor (ADDSUB8): eight XOR gates invert B under control of SUB, which also seeds the carry-in. SUB = 0 adds, SUB = 1 subtracts. Open it in the lab; compute 5 - 3 and read 2, then 3 - 5 and read the two's-complement pattern for -2._

> **TIP:** When you compute `3 - 5` the result `1111 1110` is `-2` in two's complement. The probes show the raw bits; reading them as signed is a matter of interpretation, not extra hardware. The same `1111 1110` is `254` if you decide the byte is unsigned. The CPU stores bits; signedness lives in how you read them.

## A harder road: sign-magnitude subtraction

Two's complement is not the only way to write negatives. The oldest scheme, **sign-magnitude**, is the one people use by hand: reserve the top bit as a pure sign flag (`0` for positive, `1` for negative) and let the remaining bits carry the plain unsigned magnitude. With one sign bit and four magnitude bits, `+6` is `0 0110` and `-6` is `1 0110`, so only the sign bit moves and the magnitude `0110` stays put. Two's complement, by contrast, rewrites every bit to negate. Sign-magnitude is easy to read, but it pushes the effort onto the hardware, and subtraction is where that shows.

A plain magnitude subtractor (the same adder/subtractor from above, run in subtract mode) returns the right answer only when the first operand is the larger one. Give it `M - S` with `M` greater than or equal to `S` and it hands back `M - S` cleanly. Give it `M - S` with `M` smaller than `S` and it underflows: it tries to borrow past a top bit that is not there, and the magnitude bits come out wrong.

> **WARN:** **Watch the underflow.** Suppose you want `6 - 9` with 4-bit magnitudes. A 4-bit subtractor computing `6 - 9` cannot fit `-3` into four magnitude bits, so it wraps: the output bits come out `1101` (which reads as `13`) with a borrow off the top, not the `3` you wanted. Sign-magnitude has a second quirk as well: it holds **two zeros**, `0 0000` for `+0` and `1 0000` for `-0`, which downstream logic must treat as equal. Two's complement dodges both problems: its bits are already correct for any order of operands, and it has exactly one zero.

The fix is to force the subtractor to always see the larger magnitude first, while remembering which input that was so you can set the sign. That is a **compose-with-blocks** job, four familiar parts wired in a row: a comparator, a pair of multiplexers, the subtractor, and one inverter.

1. **Compare.** Feed both magnitudes into a [comparator](https://digiwleea.wleeaf.dev/learn/comparator/) and read `A >= B`, which is its `GT` output OR its `EQ` output. Call that line `AGE`, for A greater-or-equal.
2. **Swap.** Send the two magnitudes through two [multiplexers](https://digiwleea.wleeaf.dev/learn/mux/) that share `AGE` as their select line. One mux outputs the minuend `M = AGE ? A : B`; the other outputs the subtrahend `S = AGE ? B : A`. Now `M` is always the larger magnitude, so `M >= S` holds by construction.
3. **Subtract.** Feed `M` and `S` into the subtractor. Because `M >= S`, it never underflows, and its output is the correct result magnitude `M - S`.
4. **Set the sign.** The result is negative exactly when `A` was the smaller value, so the result's sign bit is simply `NOT AGE`. Put it in front of the magnitude and you have the answer in sign-magnitude form.

Trace `6 - 9`. The magnitudes are `A = 0110` and `B = 1001`. The comparator sees `6 < 9`, so `AGE = 0`. With `AGE = 0` the muxes swap the inputs: `M = B = 1001` (9) and `S = A = 0110` (6). The subtractor computes `9 - 6 = 0011` (3) with no underflow this time. The sign bit is `NOT AGE = 1`, negative, so the result is `1 0011`, which is `-3`, exactly right. Run it the other way as `9 - 6`: now `AGE = 1`, the muxes leave `M = 9` and `S = 6` in place, the subtractor gives `0011`, the sign is `NOT 1 = 0`, and the answer is `0 0011`, `+3`.

**Q (Try it):** Using the compare, swap, subtract, sign recipe, work out `3 - 10` with 4-bit magnitudes. After the swap, which value is the minuend `M`? What magnitude comes out of the subtractor, and what is the sign bit of the result?

**A:** The magnitudes are `A = 0011` (3) and `B = 1010` (10). Since `3 < 10`, `AGE = 0`, so the muxes swap: the minuend is `M = B = 1010` (10) and the subtrahend is `S = A = 0011` (3). The subtractor computes `10 - 3 = 0111` (7). The sign bit is `NOT AGE = 1`, negative. The result is `1 0111`, which is `-7`, and indeed `3 - 10 = -7`.

Add up the cost. Sign-magnitude subtraction needed a comparator, two multiplexers, a subtractor, an inverter, and special care for `-0`. The [two's complement](https://digiwleea.wleeaf.dev/learn/twos-complement/) adder/subtractor at the top of this lesson needed one adder, one XOR per bit, and a single control wire, with no comparison and no swap: the same two numbers go in and the correct signed result comes out every time. That gap is exactly why nearly every processor stores signed integers in two's complement, and reserves sign-magnitude for places like the sign of a [floating point](https://digiwleea.wleeaf.dev/learn/floating-point/) number, where a one-bit sign flip is precisely what you want.

> **KEY:** Now one block adds and subtracts under a control bit. Add a couple more operations (bitwise [AND](https://digiwleea.wleeaf.dev/learn/and/), [OR](https://digiwleea.wleeaf.dev/learn/or/)) and a flag that reports when the result is zero, and you have the [ALU](https://digiwleea.wleeaf.dev/learn/alu/), the arithmetic and logic engine at the center of the CPU.

### FAQ

**Q:** How does a computer subtract using two's complement?

**A:** It turns subtraction into addition: `A - B = A + (NOT B) + 1`. To compute `A - B`, the hardware inverts every bit of `B` and adds `1` (by setting the carry-in to `1`), then the ordinary [8-bit adder](https://digiwleea.wleeaf.dev/learn/adder8/) does the rest. There is no separate borrow circuit.

**Q:** Why does "flip every bit and add 1" negate a number?

**A:** Flipping all bits of `B` gives `255 - B` (the **ones' complement**); adding `1` makes `256 - B`. In 8-bit arithmetic the `256` wraps to `0`, so `A + (256 - B)` lands on `A - B`. Negation is just inversion plus a carry-in of `1`.

**Q:** How is a subtractor different from a plain adder?

**A:** It is the **same** adder plus one [XOR](https://digiwleea.wleeaf.dev/learn/xor/) gate on each `B` wire, all fed by a shared control line `SUB`. Since `X XOR 0 = X` and `X XOR 1 = NOT X`, the XOR is a controllable inverter: `SUB = 0` passes `B` through for `A + B`, while `SUB = 1` flips `B` and (feeding `SUB` into the carry-in too) computes `A - B`. One control bit picks the operation.

**Q:** How can the same 8 wires hold a negative number?

**A:** **Two's complement** spends half of the 256 patterns on negatives: top bit `0` means `0` to `127`, top bit `1` means `-128` to `-1`. The CPU only ever stores bits; signedness lives in how you read them, so `1111 1110` is `-2` signed or `254` unsigned with no extra hardware.

**Q:** How does sign-magnitude subtraction work?

**A:** Sign-magnitude stores a number as a sign bit plus a plain magnitude, so subtracting two of them takes several blocks: compare the two magnitudes, use [multiplexers](https://digiwleea.wleeaf.dev/learn/mux/) to send the larger one into the subtractor as the minuend, subtract to get the result magnitude, then set the result's sign from which input was larger. A bare magnitude subtractor is wrong whenever the first operand is the smaller one, which is why the compare-and-swap step is needed.

**Q:** Why did two's complement replace sign-magnitude for integers?

**A:** Two's complement turns subtraction into one addition with a bit-flip and a carry-in, using a single adder and no comparison, and it has just one zero. Sign-magnitude subtraction instead needs a [comparator](https://digiwleea.wleeaf.dev/learn/comparator/), two [multiplexers](https://digiwleea.wleeaf.dev/learn/mux/), a subtractor, an inverter, and special handling for its two zeros (`+0` and `-0`). Two's complement is far less hardware for the same result, so processors use it for signed integers and reserve sign-magnitude for places like the sign of a [floating point](https://digiwleea.wleeaf.dev/learn/floating-point/) number.
