Where we are: inside the ALU's adder
In the previous guide you met the ALU as the datapath's calculator: a block that takes two operands plus a control code and returns a result. We treated its 'add' wire as a black box. Now we open the box. The honest news is that almost everything an ALU does for integer math reduces to one circuit — an adder — plus a few cheap tricks around it. Subtraction is addition in disguise; comparison is subtraction you throw away. If you understand the adder and its flags, you understand the arithmetic heart of the machine.
Recall too from the logic rung that a full adder is a tiny combinational block with three one-bit inputs — two operand bits a and b plus a carry-in — and two outputs: a sum bit and a carry-out. Chaining n of them, each one's carry-out feeding the next one's carry-in, gives an n-bit ripple-carry adder. That chain is literally the same long-hand addition you learned as a child, carrying from the ones column to the tens, except in base 2 and with only ones and zeros.
Binary addition, column by column
Binary addition follows exactly the rules of decimal addition, just with a much smaller multiplication table: 0+0 is 0, 0+1 is 1, 1+1 is 0 carry 1, and 1+1+1 (when a carry arrives) is 1 carry 1. You start at the rightmost column, the least-significant bit, add the two bits plus any incoming carry, write down the low bit of the answer, and push any carry one column to the left. The carry rippling leftward is exactly why the basic adder is called 'ripple-carry'.
Take a concrete case: 87 + 58 in 8 bits. In binary that is 01010111 + 00111010, and adding column by column gives 10010001, with no carry leaving the top column. Now look hard at that result, because it carries a warning that the next sections unpack. Read those eight bits as an unsigned integer and the answer is a perfectly correct 145. But read the very same bits as signed two's complement, where 8 bits only reach 127, and 145 is out of range — the pattern 10010001 actually means -111. Identical wires, identical addition, two different verdicts. The bits cannot tell you which interpretation you intended; that is your job, and the ALU just raises both alarms.
Subtraction for free: complement and add
Here is the payoff of the two's-complement scheme you learned in the data rung. To compute a - b, the hardware does not build a separate subtractor. It computes a + (-b), and negating b in two's complement means 'flip every bit of b, then add 1'. The flip is free — just invert each wire with a NOT gate. The 'add 1' is also free, because the adder already has a carry-in to its rightmost column: just feed it a 1. So subtraction reuses the very same ripple-carry adder with two cheap modifications, and that is why your earlier guide promised that subtraction would come out 'free'.
This sharing is one of the most satisfying ideas in all of computer arithmetic, and it explains a deep design choice. The whole reason the industry abandoned sign-magnitude and ones-complement for two's complement was not elegance on paper — it was that two's complement lets one adder serve both operations with one extra control wire, with no special cases and only a single zero. Comparison falls out too: to test whether a equals b or a is less than b, the ALU subtracts and inspects the flags, never keeping the difference.
Two alarms: carry versus overflow
Now the part everyone confuses. After an add, the ALU sets several condition flags, and two of them sound very similar but mean completely different things. The carry flag simply records whether a carry left the most-significant column. It is the right alarm for unsigned arithmetic: if you add two unsigned numbers and a carry escapes the top bit, the true sum needed more bits than you have, so the unsigned result wrapped around. Carry is about running out of room in the unsigned world.
The overflow flag is the alarm for signed two's-complement arithmetic, and it is a different test entirely. Signed overflow happens when the true mathematical result falls outside the signed range — for 8 bits, outside -128..127 — even though no carry may leave the top bit at all. The give-away is sign: overflow occurs exactly when you add two numbers of the same sign and get a result of the opposite sign. Two positives that sum to a 'negative', or two negatives that sum to a 'positive', is impossible in real math, so the bits must have wrapped.
8-bit, signed two's complement (range -128..127)
64 + 64 : 01000000 + 01000000 = 10000000 = -128
same sign in, opposite sign out -> OVERFLOW set
carry out of MSB = 0 -> CARRY clear
255 + 1 (read as unsigned 0..255):
11111111 + 00000001 = 00000000 = 0 (wrapped)
carry out of MSB = 1 -> CARRY set
read as signed -1 + 1 = 0 -> OVERFLOW clear
Carry -> unsigned wrapped. Overflow -> signed wrapped. Independent!Read that trace twice: the two flags are genuinely independent. In the first line overflow fires but carry does not; in the second, carry fires but overflow does not. The hardware computes overflow cheaply as the XOR of the carry into the top bit and the carry out of the top bit — when those two disagree, the sign got corrupted. The crucial honesty here is that the silicon never decides for you which alarm matters. A C compiler emitting a check after a signed add looks at overflow; after an unsigned add it looks at carry. The same adder, the same bits, but the language's type system chooses which flag is the real warning.
Honest surprises and where this leads
A few truths worth holding onto. First, hardware overflow is silent by default: the bits simply wrap, the flag is set, and unless something reads that flag the program sails on with a wrong number. Many real bugs and security holes are exactly this — a length or index that wrapped past its maximum. Second, there is one asymmetry in two's complement to respect: the most-negative value (for 8 bits, -128) has no positive twin, so negating it overflows and gives you -128 right back. Flip and add 1 to 10000000 and you land on 10000000 again; the math has nowhere to put +128.
From this one adder the rest of integer arithmetic grows. Multiplication is, at heart, a stack of shifted additions (shift-and-add, sped up by Booth's algorithm and array multipliers); division is repeated subtract-and-shift, and notoriously the slowest of the four because each step depends on the last. Floating point then wraps signed integer arithmetic in machinery for exponents, normalization, and rounding. But every one of those builds on what you now hold: bits added column by column, subtraction recycled as add-the-complement, and two honest little flags that tell you when the answer fell off the edge.