signed
unsigned
hex
24-bit interactive adder
inputs
+0
0
#0
Input A
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
+
-
+0
0
#0
Input B
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
+
-
Carry
24
Carries
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
Inv (Subtract)
+0
0
#0
Adder A
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
+0
0
#0
Adder B
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
+0
0
#0
Result
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
Flags
Z
S
C
O

24-bitCPU ALU Adder Simulator

Hello! This shows how computers do integer (whole-number) addition in binary. The simulator above lets you tinker around with addition and subtraction like a computer would see it. Being interactive is supposed to help the process feel more intuitive, so go ahead and play with it and read on if you want more details.

This tool is a companion to my Sprout24 CPU project. I'm building up some documentation and learning material, and this is going to be part of that larger effort.

Binary Digits and Unsigned Numbers

We are looking at a 24-bit adder here, which means that as far as this simulated computer can represent, there are 224 — or 16,777,216 — different possible numbers.

Since binary is another word for Base-2, each digit can only have two possible values. In our usual Base-10, each digit can be any number 0–9. Here, though, each digit can be only be 0 or 1. "Off" and "on" are another way to think about it.

In this simulator, "1" or "on" bits are highlighted red, while "0" or "off" bits are grey. See the top two rows of bits labeled "Input A" and "Input B"? Go ahead and click on any of those input bits. By switching them on and off, you're changing the digits of the two binary numbers that the computer is going to be adding together.

The most natural way to understand these numbers is that any combination of 24 bits will map to numbers from zero (all bits off) to 224 - 1. Those are considered unsigned numbers: 0 through 16,777,215.

Negative Numbers and Ones-Complement

That's simple enough. But negative numbers exist, too, and there's no room for them in that range. What if we could split that range in half? We could leave half of the numbers on the positive side, but let the other half represent negative numbers.

One way to do this is to just reserve the top bit to indicate whether the rest of the number is positive or negative. So going from all-bits-off to all bits-on, you'd count up from zero up to 8,388,607, then flip the sign and keep going from -8,388,607 down to -0 before running out of digits.

Fair enough. That representation for signed numbers is called ones'-complement, and some old computers did use it. But it's kind of wonky. We'd have two sort-of-equivalent numbers with different representations: +0 (all bits off) and -0 (all bits on). And it turns out there's a better way to handle it.

Twos'-Complement: Better Negative Numbers

What if we shift the representation to get rid of one of those redundant zeroes? Instead of -0, what if we decide that all-bits-on represents -1 instead? Then when we go from all-bits-off to all-bits-on, we go zero through 8,388,607, then the next number is -8,388,608 instead of -8,388,607, then count down the rest of the way until all-bits-on is -1. This is called a twos'-complement representation, and is what basically all modern computers use, including the Sprout24 CPU and this simulator.

And it ultimately makes the math and the design of the computer easier. Changing the sign of a number requires flipping all the bits and adding 1. But when you do that, subtraction works out more cleanly.

Subtraction

Since subtraction is just the inverse of addition, we can turn any subtraction operation into an addition operation by switching the second number from positive to negative (or vice-versa!) and just adding those two numbers. So in the simulator here, notice that if you click the "Inv (Subtract)" checkbox, the value in the "Adder B" box changes. Because we're using twos'-complement, it's just all the bits from "Input B" flipped, then adding 1 to that modified value. From then on, the adder just treats it as any other addition.

Note that "Adder A" is always the same as "Input A". It's only the second number "Input B" that gets negated when we're treating the operation as a subtraction.

Signed vs. Unsigned

This all means that the same combination of 24 bits might have a different meaning depending on whether we're interpreting those bits as an unsigned or a signed value. For the first half of the range, numbers mean the same thing in unsigned and signed versions. It's only when you get to the top half that they diverge in meaning.

This simulator shows every number in three columns on the left. The first column is the bit pattern interpreted as a signed number. The second column interprets it as an unsigned number. And the third column is the same unsigned number, just in hexadecimal (Base-16) instead of Base-10.

Input Fields

In addition to clicking on the input bits to change them, you can just enter numbers into the two fields on the right side. The field always shows the unsigned interpretation of the numbers, but you can type in a valid negative number and it will auto-convert for you. Just hit enter after putting in a number, and it will run the addition and recalculate everything.

Carries

The carry indicators above the two Adder values light up when the column to its right has two or more of its A, B, and Carry bits lit up. It's just like carrying the 1 when doing regular old Base-10 addition, but in this case the carry happens when the column adds up to 2 or more rather than 10 or more.

You can see how it takes time for the result and carry bits to propagate from right to left, since each column depends on the column to the right, and the speed of transistors is not infinite. In this simulator, we've slowed it down to about 50 milliseconds per bit, but in a real computer we're measuring in nanoseconds. Still, the propagation delay is actually enough of a concern that real computers (including the Sprout 24) use some tricks to combine some pieces of the carry operations to "look ahead" and allow the addition to complete faster. Since the CPU can only clock as fast as its slowest propagation path, it makes sense to add the extra complexity and logic gates to try to avoid long propagation times. This simulator shows the basic propagation method since it's easiest to understand, but I may add an option to visualize the carry-lookahead method as well in the future.

There's one carry bit past the highest column at the top that is generated by the result of that highest column. We call that the "carry out" value, and we keep track of it so that the program running on the computer can tell the answer is large enough that it doesn't fit in the result value.

Flags

With that, let's look at the "Flags" box in the lower-right corner. Those are four signals that the adder sends back to the rest of the CPU along with the addition result. Here's what they mean:

(Z) Zero: This signal is turned on when all the bits in the result are off, meaning the result of the operation was zero.

(S) Sign: This signal is turned on when the most-significant bit of the result (position 23) is turned on. This is an indication that, if you're interpreting the result as a signed number, then you need to view the result as negative.

(C) Carry: This signal is turned on when the result of adding two unsigned numbers gives a result larger than what fits in the result, and the top bit "spills out" the top through the Carry-Out bit. When the checkbox for Subtraction mode is checked, this value is inverted so that it is the opposite of the Carry-Out bit, which in subtraction effectively means the Adder B value was larger than Adder A and it would have had to "borrow" a bit from the next column if it could. Note that the carry flag only makes sense when interpreting values as unsigned; it's not meaningful when interpreting numbers as signed values.

(O) Overflow: This serves a similar purpose to the Carry flag, but for operations interpreted as using signed numbers. Basically if you add two positive signed numbers and the result is negative, or you add two negative numbers and the result is positive, then you know your addition spilled over across the sign boundary and the the result isn't what it seems. The Overflow flag is meaningless if you're interpreting the values as unsigned numbers.

These flags are important because they allow the CPU to compare values and effectively make if-then decisions. That's a topic for another day.

What Else?

This simulator was built to show 24-bit addition to match the Sprout24 CPU, but it's easier to intuitively grasp all this with smaller ranges of numbers. If you want, you can switch to 8-bit or even 4-bit modes to be more cozy. Remember that our modern computers are mostly 64-bit, so the numbers they work with natively can be galactic-scale enormous.

This page is a draft for a larger set of learning material, but it's useful enough that I wanted to share it now. I looked for a similar interactive adder out there and came up pretty empty, so hopefully this proves helpful. Thanks for checking it out.

~ Autumn
@[email protected]