◈ computers mapVol 1 · Ch 06/19
How Computers Work from the transistor up · chapter 06

06Building the Adder

Chapter 5 ended on a promise I now have to keep. The adder is built out of gates you already own. You've owned every one of them since Chapter 2 — the AND, the OR, the NOT, the NAND, the NOR, the XOR. Two of those six were doing arithmetic the whole time, and nobody told you. This is the chapter where you find out which two, and why. It's one of my favourites in the book, because it's the exact seam where logic turns into math. We'll start as small as it gets: adding a single 1 to a single 1, and watching two output bits fall out — a sum and a carry. Then comes the jolt. I'm not going to hand you that one; you're going to catch it. All I'll promise is this: it isn't a coincidence you have to memorize. It's a thing you can see. And once you see it, the addition table stops being arithmetic you were taught and becomes a circuit you can wire. From there we climb one honest rung at a time. A half adder from those two gates. A full adder that can accept a carry coming in. Eight of them chained into a real 8-bit adder — the arithmetic spine of every processor ever shipped. Then, in one tight closing move, a single control wire that makes the very same block subtract on command. That last block has a name you've heard: the ALU. There's no magic anywhere in it — just gates settling into the answer we cornered them into giving.

01When gates became arithmetic

Let's start with the smallest addition there is. Take two single bits — call them A and B — and add them the way grade school taught you, one column at a time. Three of the four cases are boring: 0+0 is 0, 0+1 is 1, 1+0 is 1. It's the fourth that's interesting, and it's the one binary forces on us early: 1+1. In our two-symbol world there's no digit "2" to write. So the column rolls over: you write 0 and carry a 1 to the next column up. That's exactly the roll-over you watched on the binary odometer in Chapter 4. So here's the honest truth. Adding two bits doesn't produce one bit — it produces two: a sum bit for this column and a carry bit for the next. Toggle A and B below and watch both outputs.

the sum, worked in binary 0 A + 0 B click a box to flip 0 ↔ 1 0 0 carry 2s sum 1s 0 + 0 = 0 every case A B carry sum 0 0 0 0 0 1 0 1 1 0 0 1 1 1 1 0 1 + 1 = 2, and 2 in binary is "1 0" binary out: 00 that is 0 in decimal
input A 0 OFF
input B 0 OFF
0 + 0 → sum 0, carry 0
Two bits go in; two bits come out — a sum and a carry. Everything is fine until 1 + 1: the sum rolls over to 0 and the carry clicks up to 1. That runaway carry is the whole reason the next figure exists.
Fig 1. Add two one-bit numbers and you can’t always answer in one bit. Click A and B to flip them and watch the sum and the carry update: 0+0, 0+1, 1+0 all fit in a single sum bit with the carry resting at 0 — but 1+1 equals 2, which no single bit can hold, so the sum rolls over to 0 and the carry clicks up to 1. Read the two outputs together, carry then sum, and you get the binary number 10 — exactly two. That escaping carry is the problem the rest of the adder is built to catch.

Now stare at just the sum column of that table — the low bit, ignoring the carry for a second. It reads: 0, 1, 1, 0. Don't let me name it yet. You walked out of Chapter 2 owning six gates, and one of them already produces that exact column from those exact inputs. Go and find it before you read on. Here's your only clue: the sum is 1 exactly when the two inputs disagree, and 0 when they match. Got it? It's XOR. "Output 1 only when the inputs differ" was XOR's whole personality, and that personality is the sum of two bits. Not a resemblance. The same four rows, in the same order, letter for letter. Here's XOR again below — read its output column, then look back at the sum column, and watch them turn out to be one column printed twice.

A 0 B 0 XOR OUT 0
inputs match · out = 0
ABOUT
000
011
101
110
the odd one out: XOR fires only when the inputs disagreeeither, but not both. Hold that pattern; it's the sum bit when you add two binary digits.
Fig 2. The XOR gate — the family’s odd one out. Its output goes high only when its two inputs disagree: 0&1 or 1&0 light it, while 0&0 and 1&1 leave it dark. Read it as “either, but not both.” Toggle A and B and watch the lamp track the same/different pattern rather than any single input — that exact behaviour is the sum digit when you add two bits (0+1=1, but 1+1=0 with a carry), which is why XOR sits at the heart of binary addition.

Now do the same with the carry column — the high bit that only fires on the last row. It reads: 0, 0, 0, 1. A carry happens in exactly one case: when both inputs are 1, and never otherwise. That's the most demanding gate in the family, the one that insists on both: the AND gate, also straight from Chapter 2. So the carry of a one-bit addition is simply A AND B. Here's AND again — check its single lit row against the carry column above.

A B 0 0 click to flip AND 0 output Y truth table A B Y 000 010 100 111
Before you flip them — of the four combinations, which single one lights the output?
not both 1 → output 0
logic · and
0 ∧ 0 = 0
arithmetic · minimum
min(0, 0) = 0
sets · intersection
A ∩ B =
Watch the three tiles agree, always. Logical and, the minimum of two bits, and set intersection are not three facts to memorise — they're one operation wearing three costumes.
Fig 3. The AND gate — the demanding one. Flip the two inputs and the output lamp stays dark until both read 1. The same click ripples through three readings that never disagree: logical A ∧ B, the minimum of the two bits, and the intersection of two sets. One operation, three costumes — that's the whole trick.

Sit with what just happened, because it's the hinge of the whole chapter. We didn't design a circuit to add two bits. We noticed that a circuit we already had, wired the obvious way, was the addition. The sum is XOR. The carry is AND. Feed the same two inputs into both gates at once, and you get both output bits in a single settling step. That little two-gate assembly has a name — the half adder — and it is the atom of all arithmetic in the machine. Toggle the inputs below. Watch the sum lamp (XOR) and the carry lamp (AND) light independently, together giving you the two-bit answer to A+B.

SUM = A B CARRY = A · B A 1 B 1 XOR AND SUM the ones place CARRY the twos place 1 + 1 10 2s 1s = 2 carry · sum
← toggle the two input bits (or click a lamp-node in the diagram)
1 + 1 = 2 — the sum bit is 0, but the AND catches the overflow: carry 1. Binary 10.
The half adder — the atom of arithmetic. Add two single bits and the answer needs two lamps: a sum and a carry. Feed both bits into an XOR and its output is the sum — high when the inputs differ, exactly the last digit of 0, 1, 1, 0. Feed the same two bits into an AND and its output is the carry — high only when both are 1, the moment 1 + 1 overflows past a single bit into 10. Two gates, wired off the very same pair of wires, and you've built the thing that adds. Toggle A and B: watch the two lamps spell the two-bit answer.

02The full adder: room for a carry

The half adder is beautiful, and it is also not quite enough. I want you to run into its limitation yourself rather than take my word for it. Think about adding two multi-bit numbers — say two bytes — the way you add long numbers by hand: column by column, right to left. The rightmost column has just two bits to add, so a half adder handles it fine. But look at the second column. It has three things to add: its own two bits plus the carry that came in from the column to its right. A half adder has only two inputs. It has nowhere to put that incoming carry. Below, try to feed three bits into a two-input adder and watch it come up a wire short.

HALF ADDER exactly 2 inputs in 1 in 2 no socket 0 A bit 0 B bit 0 Cin carry from the last column 0 Sum 0 Carry-out this half adder says C0 S0 = A+B the true column sum C0 S0 = A+B+Cin
3 bits want in · 2 sockets · 0 stranded
two bits in, two bits handled — no carry arriving yet
Now raise Cin to 1 — a carry marching in from the column on the right. Where does its wire go?
Fig 5. A half adder has room for exactly two wires: A and B. But real addition happens column by column, and every column past the first has a third bit knocking at the door — the carry that marched in from the column on its right. Toggle Cin to 1 and watch its wire reach for the box and find nothing: there is no third socket. The adder shrugs, computes A+B, and drops the carry on the floor — so the answer comes out off by one. Two inputs can't absorb three bits, which means half adders can't be chained. Fixing that missing input is the whole job of the next figure.

So we need a slightly bigger part: one that adds three input bits — A, B, and a carry-in we'll call Cin — and still produces a sum and a carry-out. This is the full adder. The good news is that we build it almost entirely out of the half adder we just made. Take the sum first. But here's a snag worth stopping on. You learned XOR as "the inputs differ", and "differ" is a question you can only ask of two things. Three bits don't differ. So go back to XOR's four rows and count this time, instead of comparing. The two rows that light have exactly one input at 1. The two dark rows have zero ones and two ones. So "differ" was never the real rule. It was a two-input disguise for a bigger one: an odd number of my inputs are 1. That property has a name — parity — and unlike "differ", it doesn't care how many bits you hand it. Now the extension is free. When you add three bits, the sum is 1 whenever an odd number of them are 1. And you get that by asking the parity question twice: S = ABCin. First XOR the two data bits, then XOR the carry-in into that result.

And one more turn, because "the sum is the parity" shouldn't be a thing you take on my word. Ask what a column of three bits actually hands you. It hands you a count — how many of the three are 1 — and that count can only be 0, 1, 2 or 3. Write those four in binary: 00, 01, 10, 11. The digit you write down in the column is the low bit of that count. The carry is the high bit. So read the low bits of 0, 1, 2, 3 in order: 0, 1, 0, 1. That is precisely whether the count is odd. So the sum digit is the parity — not by resemblance, but because that is what a low bit means. XOR was never imitating addition. It was counting all along. Toggle all three inputs below and watch the sum track the parity.

XOR XOR 0 A⊕B A 0 B 0 Cin 0 click a bit to flip it 0 SUM 0 ⊕ 0 ⊕ 0 = 0
ones: 0 — even → sum 0
an even count of 1s → the sum bit is 0
Fig 6. The full adder's sum is just A ⊕ B ⊕ Cin — two XOR gates chained. The first XORs A and B; the wire between the gates carries that partial result (A⊕B); the second XORs it with the carry-in. Flip any of the three bits and watch the lit wires ripple through: the sum lands on 1 exactly when an odd number of the inputs are 1, and snaps back to 0 the moment the count is even. That parity rule is binary addition's sum digit — the carry is a separate story.

Now for the piece the source I learned from quietly skipped. It built the sum, then cut away before finishing the carry-out. Let's actually complete it, because it's not hard and you deserve the whole part. When does adding three bits carry to the next column? Whenever at least two of them are 1 — that's a majority vote. So let's not wave at the cases; let's name every row where it happens. With three bits there are exactly four: (0,1,1), (1,0,1), (1,1,0) and (1,1,1). Now watch them split. Two of those rows have both data bits at 1 — (1,1,0) and (1,1,1) — and Cin makes no difference in either. That's A AND B, the half adder's own carry. The other two — (0,1,1) and (1,0,1) — are the rows where the data bits disagree, so their XOR is 1, and the carry-in is what tips the balance. That's (AB) AND Cin. Count them off: four rows, two terms, every row caught once and no row caught twice. The two cases can't both fire, and together they cover every carry there is. So OR them and you're done — not on trust, on bookkeeping: Cout = A·B + (ABCin. Notice that we reuse the sum's XOR — nothing wasted. Build the carry-out gate live below.

A 0 B 0 Cin 0 click a pin reuses the sum's XOR XOR AND AND OR A⊕B 0 A·B 0 (A⊕B)·Cin 0 0 Cout
Cout = A·B + (A⊕B)·Cin

Cout = 0
0 of 3 inputs are 1 · minority → no carry
Two ways to carry: both data bits are 1 (that's A·B), or they disagree and the carry-in tips it (that's (A⊕B)·Cin). OR them — it's a majority vote: 1 whenever at least two of the three are 1.
Fig 7. The full adder's carry-out, completed. It's a majority vote: a carry rolls into the next column whenever at least two of the three inputs are 1. Two independent ways get you there — the data bits are both 1 (the half adder's own A·B), or they disagree so their XOR is 1 and the carry-in tips the balance ((A⊕B)·Cin) — OR-ed together into Cout = A·B + (A⊕B)·Cin. Notice the XOR isn't a new part: it's the very same gate that already computes the sum, borrowed here for free. Toggle A, B and Cin and watch each AND term settle and the OR resolve.

That's the complete full adder: three inputs, two outputs, all of it made from two XORs, two ANDs, and one OR. Every one of those you built from transistors back in Chapter 2. Before we trust it, let's do the honest thing and check it against every possible input, not just the ones I'd cherry-pick. Three inputs means 2³ = eight rows — few enough to walk in full. Step through all eight below. Confirm that on every single row, the two output bits spell the correct count of ones among the inputs: 0 through 3, in binary, as Cout and S.

the full adder FULL ADDER A 0 B 0 Cin 0 click a bit to toggle it Cout 0 the 2s place Sum 0 the 1s place the outputs spell the count ones fed in 0 = 0 0 2s 1s Cout · Sum, in binary = the adder's own outputs ✓ walk all eight rows — every input combination, checked — inputs — — outputs — A B Cin Cout Sum ones in verified
rows verified 0 / 8
step through — the outputs will match the count every time
Cout is the 2s place, Sum the 1s place — together they count how many of A, B, Cin are on.
Fig 8. The whole full adder, laid bare across all 2³ = 8 input rows. Step with next, jump by clicking any row, or toggle a single input lamp — and watch the two outputs light. Here's the quiet miracle the whole chapter was building toward: Cout and Sum aren't arbitrary — read together they spell the count of ones you fed in. Two ones in → binary 1 0; three ones in → 1 1. Every row is checked live against that correct binary count, and hitting walk all eight verifies the device exhaustively — not "usually right," but right in every case there is.

Now the move that makes everything above scale. It's a habit of mind more than a circuit. We've verified the full adder does exactly what it claims on all eight inputs. So we're allowed to stop looking inside it. We seal the whole tangle of XORs and ANDs and the OR behind a single labelled box — three pins in (A, B, Cin), two pins out (S, Cout). From here on we draw that box and never reopen it. This is abstraction, or black-boxing. Once a circuit's behaviour is trusted, its structure stops mattering. You get to build on top of the promise instead of the parts. It's the same license that let us treat a gate as a symbol instead of four transistors. Flip between the guts and the box below.

XOR AND XOR AND OR A 0 B 0 Cin 0 click to flip SUM 0 CARRY 0 FULL ADDER 1-bit · add A + B + Cin A B Cin S Co A 0 B 0 Cin 0 click to flip SUM 0 CARRY 0
A 0 · B 0 · Cin 0  →  Sum 0, Carry 0
0 + 0 + 0 = 0 → keep 0, carry 0
Five gates, one messy tangle — but you already verified it works. Click the inputs, watch Sum and Carry.
Once it's proven, you stop caring how. Flip to the box: same three pins in, two out — the tangle sealed behind one symbol you never reopen.
Fig 9. The same one-bit adder, two ways. On the left, the guts: two XORs, two ANDs, one OR, wired so that Sum = A⊕B⊕Cin and Cout = AB + Cin(A⊕B). Flip A, B, or Cin and trace the gold current through the tangle. Then hit full-adder box — nothing about the behaviour changes. That's abstraction: once you've verified the mess, you seal it behind one symbol with three pins in and two out, and you never open the lid again. The next section stacks eight of these boxes without once thinking about the gates inside.

03Ripple-carry: eight in a chain

Here's the payoff of building the full adder with a carry-in: the parts now snap together like train cars. Take two of our black-boxed full adders. Wire the carry-out of the one handling the low bit straight into the carry-in of the one handling the next bit up. That's the whole trick. The carry that "rolls over" from column to column in hand arithmetic is now a literal wire running from one adder to the next. Set the two low bits of each number below and watch a carry born in the first adder travel into the second.

1st adder · ones place 2nd adder · twos place A0 B0 A1 B1 0 0 0 0 FULL ADDER FULL ADDER a + b + carry-in a + b + carry-in carry-in 0 carry = 1 the shared wire 0 4's place 0 0 sum bit 0 (1s) sum bit 1 (2s) click a bit above to flip it — watch the carry ride the gold wire
A 00 (0) + B 00 (0) = 000 (0)
No carry yet — each column stands alone.
The carry-out pin of the ones adder is literally a wire soldered to the carry-in pin of the twos adder. "Carry the 1" stops being an arithmetic ritual and becomes a copper connection.
The carry is a wire. Two full adders, chained. Click the bits of A and B feeding the 1st adder (the ones place): when both are 1 the column overflows, a carry is born, and it travels the gold wire straight into the carry-in of the 2nd adder (the twos place). The hand-arithmetic move "carry the 1" isn't a rule you memorize here — it's a strip of copper soldered from one adder's carry-out to the next one's carry-in.

Do that eight times and you have the 8-bit adder. Eight full adders in a row — the same little atom, chained. Each one takes one bit of A and the matching bit of B. Each one's carry-out feeds the next one's carry-in, with the very first carry-in tied to 0. Feed it two whole bytes and it hands you their sum, one settling wave later. This is the arithmetic spine of every processor you have ever used, and there is nothing inside it that wasn't in that first pair of gates. Set A and B below, then watch the carry ripple left. That visible wavefront threading through the adders is the reason this design has a name: ripple-carry.

A B Σ carry‑out 0 carry‑in 0 tied to 0 ◀ the carry ripples this way
Click any bit in row A or B to flip it. Each column is one full adder; the carry it makes is fed into the next column to its left — the visible wave is what ripple-carry is named for.
A = 15  +  B = 9
15 + 9 = 24 · carry-out 0
Fig 11. Eight full adders in a row — one per bit — are all it takes to add two whole bytes. Click the bits of A and B and watch each column hand its carry to the neighbour on its left; the gold wave travelling from the 1s place up to the 128s is exactly why this is called a ripple-carry adder. The rightmost carry-in is tied to 0 (nothing carries into the ones place), and the leftmost carry-out is the 9th bit: when it lights, the true sum didn’t fit in eight bits. Try 127 + 1 to see the carry ripple the whole way, and 255 + 1 to watch the byte overflow to 0 with the carry-out held high.

That ripple is gorgeous to watch, and it is also the design's one real weakness. So let's be honest about it. The source waved at "settling time," but there's a precise cost here worth naming. Each full adder cannot compute its carry-out until its carry-in has arrived and settled. So the top adder is waiting on the seventh, which is waiting on the sixth, all the way down. The carry has to physically walk the entire chain, one adder's propagation delay at a time, before the highest sum bit is trustworthy. Add more bits, and the worst-case delay grows in a straight line with the width. It's a row of dominoes: the last one can't fall until every one before it has. Watch the wave march below.

A B Σ LSB MSB carry travels this way → Cin 0
carry-delays elapsed 0 / 8
press trigger — the carry must crawl through every adder
Fig 12. A ripple-carry adder is a row of full adders, and each one can't finish until it knows the carry from the adder below it. Hit trigger the carry and watch it march — one adder, then the next, like dominoes — the lit gold pulse crawling from the LSB up toward the MSB, whose sum bit stays an untrustworthy ? until the very last tick. Widen the adder and the wait grows right along with it: the worst-case delay is linear in width. Flip to no carry chain to see the opposite — when no column passes the carry along, every bit settles at once, no matter how wide.

Engineers hated waiting on that walk, so they invented a way around it. It's worth knowing the name, even though we won't build it in full: carry-lookahead. First, a unit to count in. One gate delay — written Δ — is simply the time a single gate takes to settle after its inputs change. That's the currency. A ripple stage costs about 2Δ, so four bits of ripple is 8Δ before the top sum bit can be trusted. Now the insight: you don't actually have to wait for a carry to arrive to know whether it will arrive. Each column either generates a carry on its own — both bits 1, which we write g = A·B — or propagates one that reaches it, meaning the bits disagree, written p = A⊕B. Both depend only on the input bits, and the input bits are all sitting there at once. So a lookahead unit computes every column's carry in parallel with extra gates instead of threading them one by one, and they all settle together at about 3Δ. Eight against three: you trade more hardware for far less delay — the classic engineering bargain. The trick works at any width — the wide ones nest lookahead units inside lookahead units — so we'll watch it on four bits, where every column fits on screen, and then go back to all eight. Compare the two schemes side by side below.

A
B
C₀
A + B + C₀ =
clock  t = 0Δ CLA 3Δ ripple 8Δ
Drag the clock. Watch the ripple carry climb one stage at a time while the lookahead carries wait, then all settle together at 3Δ.
Both circuits give the same sum. The only difference is when the carries are known — ripple pays 2 gate-delays per bit, lookahead pays a flat ~3.
Fig 13. The same 4-bit sum, computed two ways. Click the A and B bits, then drag the gate-delay clock. In ripple-carry each stage must wait for the carry below it, so the settled carries climb one bit at a time — a wavefront sweeping from C0 up to C4, costing 2 gate-delays per bit (8 for four bits). In carry-lookahead, each carry is written straight from the generate (g = A·B) and propagate (p = A⊕B) signals — Ci+1 = Gi + PiCi unrolled into one wide gate stage — so all the carries settle together at ~3Δ. More gates, far less delay: hit worst case 1111 + 0001 to watch the ripple crawl the full length while the lookahead is already done.

Ripple or lookahead, though, the behaviour is identical: same two bytes in, same sum out. And that means we get to do the black-box move one more time, at a bigger scale. The whole eight-adder chain, carries and all, collapses into a single rectangle: two 8-bit inputs, one 8-bit output, one carry-out off the top. We'll draw it as ADD and never again worry which of the two internal schemes is wired inside. That trusted rectangle is now a component — the piece we'll drop into the processor a few chapters from now without a second thought. Collapse the chain into the block below.

One more look at that rectangle before we use it, because what it doesn't know is the reason the next move is free. The ADD block has no idea what your bits mean. Hand it 1111 1111 and 0000 0001 and it hands back 0000 0000 with the top carry-out lit — and it does that whether you were thinking 255 + 1, or thinking −1 + 1. Same eight wires, same eight voltages, same dumb column-add. Nothing in the copper tells those two stories apart. Two's complement, back in Chapter 5, never changed a single bit; it changed how you read them. Signedness is a convention living in your head, not a signal the machine can sense. That also settles something you may have started nagging at. At the 8-bit adder I made a fuss of the top carry-out: light it and the unsigned sum didn't fit in eight bits. In a moment you'll watch a subtraction throw that same bit away. Both are true, and the pin never budges. It answers one question — did the column-add run off the end of the byte? — and you decide what that answer is worth. Read the byte as unsigned and running off the end is overflow. Read it on Chapter 5's wheel and running off the end is one full lap, worth exactly 0. One pin, one behaviour, two readings, because you brought two conventions.

A + B Σ Cin 0 ADD 8-BIT A[7:0] B[7:0] SUM[7:0]
eight full adders, one rippling carry
Click any A or B bit to change the inputs — the sum and carry-out follow. Then flip ripple ↔ lookahead: the wiring inside changes, the answer never does. That's why we collapse it to one box.
The same 8-bit adder, told twice. On the left of the switch: eight full adders, each one's carry-out wired into the next — flip ripple to lookahead and the internal carry logic changes completely, yet the sum and the carry-out never budge. Because the behaviour is fixed no matter how you wire the inside, you're free to stop drawing the wires and keep a single trusted rectangle: two 8-bit inputs, one 8-bit sum, one carry-out. That box is ADD — the piece every later chapter reaches for.

04Subtraction for free — the ALU

We built an adder. We are about to get a subtractor without building anything that deserves the name. This is where Chapter 5 comes back to collect. Recall the prize from last chapter: subtraction was defined away. AB is just A + (−B). And in two's complement, you make −B by inverting every bit of B and adding one. Our adder already does the "+". All we need is a way to hand it an inverted B and an extra 1. Here's that idea again — subtraction riding the same adder — before we wire it into hardware.

the subtraction how −B is made the one adder — identical circuitry for + and − 4-bit adder · dumb column-by-column 1 2 4 −8 + A −B
A−B is A+(−B). Watch the negate-then-add flow through the one adder — it never learns it subtracted.
Fig 15. The payoff of the whole chapter: a machine with no subtractor in it subtracting anyway. Pick any A − B and step it through. The subtraction rewrites itself as A + (−B); −B is built by the two-step reflex — flip the bits, add one; then A and −B pour into the identical four-bit adder, column by column, carries and all. On 7 − 5 the top carry drops off the end — a full lap around the wheel, worth 0 — and out falls 2. The adder did the same dumb column-add it always does. It never knew it subtracted, and that's exactly why two's complement won.

So how do we invert B — but only sometimes, on command — so the block can add when we want and subtract when we want? The answer is a gate we've been underusing. Look hard at XOR with one input tied to a control line C. When C is 0, B ⊕ 0 = B — the bit passes through untouched. When C is 1, B ⊕ 1 = NOT B — the bit comes out flipped. So a single XOR is a controlled inverter: a NOT gate with a switch on it. Toggle the control line below and watch one XOR either wave the bit through or flip it.

So the invert is handled. Eight of those XORs, one on each B line, and every bit of B flips the moment you say so. But read what two's complement actually asked for: invert and add one. So where is that +1 coming from? Not a second adder — refusing to build one is the whole point. Not a new gate either; adding 1 to an eight-bit number is precisely the job we just spent a chapter on. Sit in that for a second before you scroll on. Everything you need is already on the page, and has been for a while. Play with the control line below, and while you do, go looking for it.

WIRE out just copies B XOR 0 B data bit 0 C · control the switch on the NOT 0 B ⊕ C = B
One XOR, two inputs. Flip C and watch the gate change its mind about B.
C = 0 → out copies B, untouched
A lone XOR is a NOT gate with a switch. Hold C = 0 and it's a plain wire — B walks straight through. Set C = 1 and it becomes an inverter — every B comes out flipped.
Fig 16. One XOR gate is a NOT with a switch on it. The top input carries the data bit B; the bottom input, C, is the switch. Hold C = 0 and the gate is nothing but a wire — B walks straight out unchanged (0⊕0=0, 1⊕0=1). Flip C = 1 and the same gate becomes an inverter — every B comes out flipped (0⊕1=1, 1⊕1=0). That is the whole trick the adder leans on next: one control line decides whether a number passes through or gets negated.

Found it? It's the one pin in this whole machine that we tied off and never used again. When we chained eight full adders, we grounded the lowest carry-in, because in ordinary addition nothing carries into the ones column. But grounding it was a choice, not a weld. It's an input like any other, and look where it sits: the ones column, place value 20. So driving it to 1 adds exactly one to the total — not two, not eight, one — and it costs no gate at all. The cheapest +1 in the building. Now watch the whole thing close in one move, and notice that it's a single wire, not a second machine. Put one controlled inverter on each of the eight B lines. Then run one control wire — call it the add/subtract line — to every one of those XORs and to that forgotten carry-in at the same time. Set that line to 0, and B passes straight through, carry-in is 0, and the block adds. Set it to 1, and every bit of B inverts and the carry-in becomes the "+1". That's exactly invert-and-add-one, exactly −B, so the block subtracts. One toggle, eight XORs, and the adder you already trusted now does both. Flip it below.

add mode — B passes straight through, carry-in 0 → A + B
Same A, same B. Flip the one line: it inverts every bit of B through the eight XORs and pushes a 1 into carry-in — B becomes −B, and the adder subtracts. Click any A or B bit to change the numbers.
One line, two jobs. That single add/subtract wire fans out to eight XOR gates — each one a controlled inverter that passes B untouched when the line is 0 and flips it bit-for-bit when the line is 1 — and the very same wire drops into the adder's carry-in. Invert every bit of B and add one, and you have exactly −B in two's complement, so the block that added a moment ago now subtracts the identical operands. Flip the toggle (or the line itself) and watch the whole 8-bit slab switch between + and − with one move.

Give that block its real name. An adder that also subtracts on command — an 8-bit datapath that performs an arithmetic operation you select — is the germ of the ALU, the arithmetic logic unit, the calculating core at the centre of every CPU. Ours does two operations so far, add and subtract, chosen by one line. One thing to settle before we seal it, because this one catches working engineers for years. Subtract 5 from 7 and the top carry-out lights up. Subtract 7 from 5 and it stays dark. Read that the natural way round and you'd say the lamp means "it borrowed" — and you'd have it exactly backwards. A lit carry-out means the subtraction never needed to borrow: A was at least as big as B. Dark means it did. Same pin, same behaviour it has always had; only the question you're asking of it changed. A real ALU stacks a few more operations — the bitwise AND, OR, XOR of Chapter 18 hang off the very same operand lines — and widens the selector to pick among them. But the shape is already here: operands in, an op-select in, one result out. Black-box it, label it ALU, and meet the last component we'll build before the machine starts to remember. Explore it below.

ALU 13 − 5 SUBTRACT one adder · B inverted · Cin = 1 A = 13 B = 5 op-select: SUB one control line picks the operation RESULT 8 0b1000 no borrow
1101 − 0101 = 1000 · no borrow
Same box, same wires — the op-select alone decides what comes out.
Fig 18. Meet the ALU — arithmetic logic unit. It's a black box with the same three ports every time: two operands in the left, one op-select line in the bottom, one result out the right. Feed it A and B, then flip the op-select. SUB reuses the very adder that does ADD — it just inverts B and adds one (two's complement), and its carry-out, lit, means it never had to borrow. Bolt a few logic ops (AND, OR, XOR) onto that same select line and the adder-that-subtracts has quietly become the calculating core of every CPU.

One claim this big shouldn't rest on the handful of examples I chose to show you. So let's check it the honest way: exhaustively, in code. Here's a full adder written as pure gate logic — literally XOR, AND, and OR on single bits. It's composed eight times into a ripple-carry adder, then run against the language's own + for a spread of byte pairs, with the results diffed. Not "usually" right: bit-for-bit identical, because the gates are the arithmetic. Read it and run it below.

# a FULL ADDER — three logic gates on single bits (0 or 1)
def full_adder(a, b, cin):
    s    = a ^ b ^ cin                 # XOR  → sum bit
    cout = (a & b) | (cin & (a ^ b))   # AND,AND,OR → carry
    return s, cout

# chain 8 of them; the carry ripples low → high
def ripple_add(A, B):                  # A, B are bytes 0..255
    carry, out = 0, 0
    for i in range(8):
        a, b = (A >> i) & 1, (B >> i) & 1
        s, carry = full_adder(a, b, carry)
        out |= s << i
    return out | (carry << 8)          # 9th bit = final carry

# the whole point — no math, just gates:
for A in range(256):
    for B in range(256):
        assert ripple_add(A, B) == A + B
gates & native + agree on this pair
Nothing in ripple_add knows what “plus” means. It only shuffles bits through XOR, AND, OR — yet it matches + on every one of the 65,536 possible byte pairs. The gates are the arithmetic.
Fig 19. A full adder is nothing but three logic gates on single bits — XOR for the sum, AND/AND/OR for the carry. Chain eight of them and let the carry ripple from the lowest bit to the highest, and you have a machine that adds two bytes. Drag A and B to watch the carry climb the chain; the console diffs the gates’ answer against the language’s native +. Then run the proof by exhaustion: across all 65,536 possible byte pairs, the gate-level adder matches + bit-for-bit, every time. The arithmetic was never added on top — the gates are the arithmetic.

And that's Chapter 6 — a working ALU, built from nothing but the gates of Chapter 2 and the number sense of Chapters 4 and 5. The whole climb was one idea, reused. The sum of two bits is XOR and their carry is AND, so a half adder is two gates. A full adder adds a carry-in, so the parts chain. Eight chained is an 8-bit adder, its ripple-carry paid for in propagation delay. And one add/subtract line through eight controlled inverters buys subtraction for free. At every step we black-boxed what we trusted and built on the promise. Here's a caveat to carry forward, honestly: this machine does whole numbers only. There are no fractions on these wires, no decimal point anywhere in the byte. Making one is a whole separate story the machine doesn't tell for a long time. But here's the deeper problem, the one that opens the next chapter. You've built a calculator that answers the instant you set its inputs — and that's exactly the trouble. Touch an input and the old answer vanishes. The sum lives only while you hold the operands still. To reuse a result — to feed today's sum into tomorrow's addition — you have to make the machine hold a value on its own. And pure gates, which only ever react, cannot. For that we need something that can remember. Memory, it turns out, is what you get when you do the one thing we've carefully never done: bend a wire back on itself.

iolinked.com
Written by Ajai Raj