Digital Systems 3 min read

Binary addition and subtraction

Binary addition works like decimal, but a carry appears whenever a column reaches 2. A CPU subtracts by adding the 2's complement, and it reports two different problems with two flags: carry for unsigned results, overflow for signed ones.

Seven is 0111 and three is 0011. Inverting three gives 1100 and adding one gives 1101, which is minus three. Adding 0111 and 1101 gives 1 0100. The carry out of the top is dropped, leaving 0100, which is four.
7 - 3 as 7 + (-3): add 1101, drop the carry out of the top, and 0100 (4) remains.

Adding bit by bit

Each column adds two bits plus any carry in: 0 + 0 = 0, 0 + 1 = 1, and 1 + 1 = 10, which is 0 with a carry of 1 to the next column. In 4 bits, 6 + 3 is 0110 + 0011 = 1001, which is 9.

Carry and overflow are different

A result that does not fit in the width loses its top bit. 1100 (12) + 0101 (5) is 1 0001: the carry out of the top is 1 and the register keeps 0001. For unsigned numbers, a carry out means the answer is wrong.

For signed numbers the test is different. 0101 (5) + 0100 (4) gives 1001, which reads as -7, although there was no carry out. That is signed overflow: two positives gave a negative. Most CPUs, including Arm Cortex-M, keep both as flags (C and V) in the status register, so the same add instruction serves both kinds of number and your code checks the right flag.

Subtracting is adding

Subtraction reuses the adder. To compute 7 - 3, take the 2's complement of 3 (0011 inverts to 1100, plus 1 is 1101, which is -3) and add: 0111 + 1101 = 1 0100. Drop the carry out and you have 0100, which is 4. A chip needs no separate subtractor, only an inverter and a carry in of 1.

uint8_t a = 200, b = 100;
uint8_t sum = a + b;   // 300 does not fit: stored as 44 (0x2C)

In C, arithmetic on small types is promoted to int first, so the wrap shows up when you store the result back into 8 bits. Know your width, and test the edges.