Arithmetic Logic Unit (ALU) Explained





Every electronic device that works with data - your PC, phone, or smart TV - uses a Central Processing Unit (CPU), at the heart of every CPU lies an Arithmetic Logic Unit (ALU).

An Arithmetic Logic Unit (ALU) is a combinational digital circuit that performs arithmetic and bitwise operations on integer binary numbers.

Without the ALU, your CPU wouldn’t be able to make mathematical decisions. And everything inside your electronic device comes down to math at the bit level.

If you're reading Arithmetic Logic Unit (ALU) Explained on your Phone or PC (probably not your TV), then you’re using an ALU.

Now you know the importance of an ALU let's look at the components used to build an ALU.

The Components Used to Build an ALU

An Arithmetic Logic Unit (ALU) is built from many components:

Including: transistors, logic gates, adders (half/full), ripple-carry circuits, multiplexers, control logic, flags, and output registers.

For the ALU I built in Rust the following operations are used: ripple-carry addition, ripple-carry subtraction, binary multiplication, and long division, all for unsigned math (> 0).

These operations relied on the logic gates: AND, NOT, OR, XOR, and Shift Left.

If you're not familiar with boolean logic or binary ADD, SUB, MULTIPLY, and DIV operations then you can dive deep into the concept of your choice at the Mathematics homepage.

Those were the components used to build an ALU. Now, let's see how the ALU works.

How an ALU Works

The job of an ALU is to constantly process data — also known as bits — which pass through transistors. Each transistor (there are about 25 billion in a Mac M3 chip) acts as a tiny switch (OPEN/CLOSED) before each gate. They work on electrons: when a small voltage is applied, the transistor “opens,” and when there’s no voltage, it “closes.”

When it’s open, current can flow (representing a 1); when it’s closed, no current flows (representing a 0).

When the bits are received at the register, they go through logic gates, perform billions of arithmetical and logical calculations in milliseconds, and form n-bit words. Those n-bit words are then sent to the output register and stored at the right address in RAM, so you can see the right patterns on your screen.

Those patterns can be characters, digits, symbols, shapes, motion, and colors.

Then we have opcode (control logic). These are patterns of bits, for example, a 6-bit opcode gives 64 possible patterns, each representing a different operation the ALU can perform. Which operations exist depends on how the ALU designer defines them.

If you were an ALU designer, you could assign the pattern 0x000011 (3) to multiplication. Then, every time the ALU sees that pattern, it knows to perform multiplication and uses logic gates (AND, OR, NOT) and a ripple-carry adder to get the result.

So the ALU is always repeating this same cycle: opcode → function → output.

You now know how an ALU works, so let's take a look at how building an ALU in Rust takes place.

Building an ALU in Rust

It all started with binary truth tables an amazing hands-on way to learn logic and how Boolean logic applies to binary numbers bit-by-bit.

I got these ideas from a few resources, which you can find in the credentials section.

Then I learned binary addition and how it works at the gate level, using pure logic for Sum and Carry Out. I built a full 32-bit ripple-carry adder in Rust (starting with a half-adder).

After that, I moved to binary subtraction, learned about Difference and Borrow/Carry Out, and built a 32-bit ripple-carry subtractor.

At first, I thought that was enough — but then I realized: what is an ALU without multiplication and division?

So I built bit shifters using loops, subtraction, and addition, and then used those to implement binary multiplication with AND, SHIFT, and ADD.

Finally, I built binary division using if...else, subtraction, and shift. With that, I completed the final arithmetic layer for this ALU.

Once all mental models were built and tested in Rust, I combined them into a single Arithmetic Logic Unit (ALU), which uses:

  • Opcode
  • Transformer: Integer to Binary
  • Arithmetic functions
  • Transformer: Binary to Integer

With these two transformers, the ALU now works with integers as input and performs bit-by-bit arithmetic under the hood.

Well, that was the process of building an ALU in Rust. Here are the mental models I've gained.

The Mental Models I've Gained

The deepest mental model I've gained is that every program we write is like an ALU where the ALU is the parent function that takes an opcode and calls the right child function.

Those functions then perform operations, sometimes working together.

Just like in any program, there is one main function (the parent) that controls the flow, while child functions do their tasks but cannot control the parent.

Another important lesson I learned is overflow, which happens when the final carry-out of an operation cannot fit inside its byte or word at the MSB. In Rust, this causes a runtime panic in debug mode or wraps around silently in release mode.

This taught me why bit-width matters in arithmetic and why ALUs must handle overflow flags.

Credentials

I thank Understanding Computer Organization from First Principles, chapters 1 - 3 of Nand2Tetris and, chapters 1–8 of Code: The Hidden Language of Computer Hardware and Software.

This blog and these books shaped my basic understanding of how PC hardware works at its lowest level.

Then we have Rust: The Programming Language, which forced me to think about hardware deeply - thanks to data types, data structures, stack/heap memory, lifetimes, borrowing, and much more.

Stay Updated

If you want to stay updated on topics like Systems Thinking, Clear Thinking, Rust, Crypto, and Philosophy, check out X/Twitter, here I’ll update you when new blogs go live, and share the mental models I’m gaining.

If you want to see the code or fork the Arithmetic Logic Unit, click here to go to the repository.

If you’ve ever built an ALU, let me know what the hardest part was for you.

You can reach me at l@lmpkessels.com or, send me a DM on X/Twitter.

Till the next one.