Lesson 3. Negative numbers and subtraction: two's complement
In picturesAfter this lesson the same adder learns to subtract: the SUB switch turns A + B into A − B. Four lamps show the flags — what the processor knows about every answer: was there a carry, is the answer zero, is it negative and did it fit in 4 bits.
3.1. The idea: numbers on a circle
A 4-bit adder counts in a circle: 15 + 1 gives 0 — the fifth digit goes into the carry. So 1111 behaves like −1: add 1 to it and you get 0. In the same way 1110 is −2 and 1000 is −8.
Let us agree: if the top bit is 1, the number is negative. Then 4 bits hold the numbers from −8 to 7. This way of writing is called two's complement. Nothing in the adder has to change: it adds bits, and what they mean is up to us.
How to get −B: flip all the bits of B and add 1. For example, 3 = 0011 → 1100 → 1101 = −3. Check: 3 + (−3) = 0011 + 1101 = 1 0000 — zero in 4 bits.
And subtracting means adding −B:
XORwith theSUBswitch flips the bits ofB: withSUB = 0a bit passes as it is, withSUB = 1it is flipped;- the "plus 1" comes from the same
SUBfed to the carry inputCIof the adder.
3.2. Flags
After an addition or a subtraction every processor keeps four bits about the answer:
C(carry) — the carry out of the top digit. When subtracting,C = 1means "no borrow":A ≥ Bunsigned;Z(zero) — the answer is zero: all digits are 0, that is aNORof all the bits;N(negative) — the answer is negative: simply the top bit of the sum;V(overflow) — the answer did not fit in the signed numbers: both operands have the same sign and the sum the other one. For example,7 + 1gives1000— "−8".
The processor decides by these flags: "if zero — jump", "if less — repeat".
3.3. Building
The same project. Delete the lesson 2 setup (8 switches, ADDER4 on the canvas, three displays); keep Power/Ground.
The idea. Subtracting B means adding −B. In two's complement −B = all the bits of B flipped, plus 1. XOR with the SUB switch does the flipping (with SUB = 0 a bit passes as it is, with SUB = 1 it is flipped), and the "plus 1" comes from the same SUB on the carry input CI of the adder.
Step 1. ADDSUB4 — addition and subtraction
| Part | Pin | Label |
|---|---|---|
| Input port | out | A0 |
| Input port | out | A1 |
| Input port | out | A2 |
| Input port | out | A3 |
| Input port | out | B0 |
| Input port | out | B1 |
| Input port | out | B2 |
| Input port | out | B3 |
| Input port | out | SUB |
| Input port | out | CI |
| XOR (bit 0) | I0 I1 O0 | B0 SUB bx0 |
| XOR (bit 1) | I0 I1 O0 | B1 SUB bx1 |
| XOR (bit 2) | I0 I1 O0 | B2 SUB bx2 |
| XOR (bit 3) | I0 I1 O0 | B3 SUB bx3 |
| ADDER4 | A0 A1 A2 A3 B0 B1 B2 B3 CI S0 S1 S2 S3 CO | A0 A1 A2 A3 bx0 bx1 bx2 bx3 CI S0 S1 S2 S3 CO |
| XOR (sign A ≠ sign S) | I0 I1 O0 | A3 S3 va |
| XOR (sign B ≠ sign S) | I0 I1 O0 | bx3 S3 vb |
| AND (overflow) | I0 I1 O0 | va vb V |
| Output port | in | S0 |
| Output port | in | S1 |
| Output port | in | S2 |
| Output port | in | S3 |
| Output port | in | CO |
| Output port | in | V |
Ctrl+G → name ADDSUB4. Pins: inputs A0–A3, B0–B3, SUB, CI; outputs S0–S3, CO, V.
V is overflow: both operands have the same sign and the sum has the other one (so 7 + 1 gives "−8").
Step 2. Canvas: switches, subtractor, flags
| Part | Pin | Label |
|---|---|---|
| Input | out | A0 |
| Input | out | A1 |
| Input | out | A2 |
| Input | out | A3 |
| Input | out | B0 |
| Input | out | B1 |
| Input | out | B2 |
| Input | out | B3 |
| Input | out | SUB |
| ADDSUB4 | A0 A1 A2 A3 B0 B1 B2 B3 SUB CI S0 S1 S2 S3 CO V | A0 A1 A2 A3 B0 B1 B2 B3 SUB SUB S0 S1 S2 S3 C V |
| OR | I0 I1 O0 | S0 S1 z01 |
| OR | I0 I1 O0 | S2 S3 z23 |
| NOR (zero) | I0 I1 O0 | z01 z23 Z |
| LED (C — carry) | in | C |
| LED (Z — zero) | in | Z |
| LED (N — sign) | in | S3 |
| LED (V — overflow) | in | V |
| Display | ⚙ | width 4, DEC, bus A |
| Display | ⚙ | width 4, DEC, bus B |
| Display | ⚙ | width 4, BIN, bus S |
The subtractor's CI goes to the same label SUB: that is the "plus 1". Lamp N is simply the top bit of the sum S3.
3.4. Check
Negative numbers in 4 bits: 1111 = −1, 1110 = −2 … 1000 = −8. The top bit is the sign.
| A | Switches A3…A0 | B | Switches B3…B0 | SUB | Display S | Lamps | Meaning |
|---|---|---|---|---|---|---|---|
| 3 | 0011 | 4 | 0100 | 0 | 0111 | — | 3 + 4 = 7 |
| 3 | 0011 | 5 | 0101 | 1 | 1110 | N | 3 − 5 = −2 |
| 5 | 0101 | 5 | 0101 | 1 | 0000 | Z, C | 5 − 5 = 0 |
| 2 | 0010 | 3 | 0011 | 1 | 1111 | N | 2 − 3 = −1 (C = 0: a borrow) |
| 7 | 0111 | 1 | 0001 | 0 | 1000 | N, V | 7 + 1 does not fit in 4 signed bits |
| 9 | 1001 | 9 | 1001 | 0 | 0010 | C, V | −7 + −7 = −14 — also an overflow |
In the "Switches" columns the top switch (A3) is on the left and A0 on the right; 1 — on, 0 — off.
When subtracting, C is lit when there was no borrow (A ≥ B unsigned) — as in most processors, the 6502 for one.
If with SUB = 1 the answer is one less, check that the subtractor's CI is on the label SUB, not on GND.
Lesson 3 paste (Cmd+I)
Needs XOR, AND, OR, NOR and ADDER4. Delete the lesson 2 setup, keep the power.
# Lesson 3 — two's complement subtraction and the flags C, Z, N, V.chip ADDSUB4 { portIn(A0) portIn(A1) portIn(A2) portIn(A3) portIn(B0) portIn(B1) portIn(B2) portIn(B3) portIn(SUB) portIn(CI) portOut(S0) portOut(S1) portOut(S2) portOut(S3) portOut(CO) portOut(V) XOR(B0, SUB, bx0) XOR(B1, SUB, bx1) XOR(B2, SUB, bx2) XOR(B3, SUB, bx3) ADDER4(A0=A0, A1=A1, A2=A2, A3=A3, B0=bx0, B1=bx1, B2=bx2, B3=bx3, CI=CI, S0=S0, S1=S1, S2=S2, S3=S3, CO=CO) XOR(A3, S3, va) XOR(bx3, S3, vb) AND(va, vb, V)} input(A0)input(A1)input(A2)input(A3)input(B0)input(B1)input(B2)input(B3)input(SUB)ADDSUB4(A0=A0, A1=A1, A2=A2, A3=A3, B0=B0, B1=B1, B2=B2, B3=B3, SUB=SUB, CI=SUB, S0=S0, S1=S1, S2=S2, S3=S3, CO=C, V=V)OR(S0, S1, z01)OR(S2, S3, z23)NOR(z01, z23, Z)led(C)led(Z)led(S3)led(V)Stuck? Something doesn't work →