Twos complement

When I was in school, I built my own processor. Not a microprocessor — it was more like a bird’s nest of wires. My focus was mainly on building a simple ALU (Arithmetic Logic Unit) with as many discrete components as reasonably possible. I added some memory, a basic control unit with a program counter, two registers, and a few status bits. The TTL chip 74181 served as my inspiration.

The control unit wasn’t exactly a marvel. It could read and write to memory and perform addition in the ALU — which didn’t support many other operations. I still remember wiring up a JNZ (Jump if Not Zero) instruction so I could implement multiplication through iteration. I was ridiculously proud when I got this entirely useless little 4-bit nibble computer working.

An adder is a relatively simple circuit, something most electronics hobbyists build early on. I didn’t need to implement subtraction. If you use two’s complement to represent negative numbers, addition and subtraction become the same operation.

The Elegance of Two’s Complement

On the really early computers, negative numbers were often represented using simple bitwise complement. So if a 4-bit word with the value 5 was 0101, then -5 would just be the opposite: 1010. Bitwise complement. That gave us a few weird results, like having two different zeros: positive zero 0000, and negative zero 1111. But this didn’t make circuitry for calculation simeple.

Soon, we figured out a better trick: two’s complement. It’s just the bitwise complement plus one. So to get -5, we take the bitwise complement of 5 (0101 becomes 1010), then add one: 1011. To flip it back to positive, we do the same in reverse: ~1011 = 0100, and 0100 + 1 = 0101.

The beauty of two’s complement is that you don’t need special circuitry for subtraction. You can just add. Since 5 - 4 is the same as 5 + (-4), we flip 4 into two’s complement form. 4 is 0100. Bitwise complement gives 1011, add one: 1100. So 5 + (-4) becomes 0101 + 1100 = (1)0001. We ignore the fifth carry bit, since we’re working with 4-bit numbers.

That carry bit always bubbles out of the word size, no matter how many bits you’re working with, because the high bits of the negative number are all 1’s.

So, no extra hardware was needed to implement subtraction in my little DIY computer, as long as I used two’s complement. Once I had a conditional jump instruction—JNZ, Jump if Not Zero—it was even possible to build multiplication through iteration. I was stuck with 4 bits, which was a bit tight. But it worked, and I knew how to add extra circuitry to make it wider.

Historical Perspective

Early Digital Equipment Corporation machines reflected this evolution. The PDP-1 used bitwise complement, but the PDP-7 moved to two’s complement — which became the norm. PDPs helped define what a minicomputer was: something you, the programmer, could actually interact with directly. No batch jobs. No operators. Just you and the machine.

Clojure and the Lisp-y Way

We can play with two’s complement directly in any language, here in Clojure:

;; Copyright Melonen
(inc (bit-not 5)) ;; => -5
(inc (bit-not -5)) ;; => 5

bit-not gives the bitwise complement, and inc adds one

We can make your own negate function?

(defn neg [x]
  (inc (bit-not x)))

Try (neg 32) — it’ll give -32. While (neg -32) will give 32. (Of course, (- 32) does the same, but where’s the fun in that?)

My Tiny ALU and Book Nostalgia

That nibble-computer taught me how things really worked. I was just a kid, but designing logic gates and watching bits flicker into meaning was unforgettable.

Years later, I read Code by Charles Petzold — “The Hidden Language of Computer Hardware and Software” — and it brought all that back. If you’ve ever wondered how a computer really works, starting with the simplest electrical circuit, it’s a wonderful journey. There’s a newer edition out, a bit thicker. Worth reading.

I remember using the classic Programming Windows 3.1 book by Petzold, when learning Windows programming

Spacewar! and PDP Machines

The first graphical video game, Spacewar!, was written for a PDP-1. It ran on a vector display — a cathode-ray tube where you controlled the beam directly. No raster scan. Just pure electron choreography. Two spaceships, orbiting a star, trying not to crash into it while blasting each other. Classic.

(Anyone remember the Vectrex console? Vector display. Played Asteroids. Magic.)

Unix and the PDPs

Unix started on the PDP-7 but truly came into its own on the PDP-11 — the first version of Unix that most people recognize. C was born there too. And yes, those machines used two’s complement. Naturally, they had a Teletype 33 as their terminal — because of course they did.

Digital’s next leap was the VAX line — Virtual Address eXtension — essentially a souped-up, 32-bit PDP with virtual memory. You even used a PDP-11 to boot the first VAX machines.

When Windows NT came along, Microsoft ditched the CP/M legacy and leaned into VMS-style architecture. The minicomputer spirit never really left us.

And Finally…

The term microcomputer once referred to a machine with the CPU on a single chip. But after NT and Linux became serious, we were all kind of back to using minicomputers again.

Labels change. Truth doesn’t.

And sometimes, in all this abstraction and progress, you realize that two’s complement is still one of the most elegant ideas in all of computing. Not bad for something built out of wires.


All #art #clojure #csharp #data-structures #database #datomic #emacs #functional #haskell #history #immutability #java #jit #jmm #lambdas #lisp #pioneers #poetry #programming #programming-philosophy #randomness #rant #reducers #repl #smalltalk #sql #threads #women