💾 Archived View for hackersphere.space › ~willowf › unix › ch01.gmi captured on 2023-11-04 at 11:35:56. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-09-28)

➡️ Next capture (2023-11-14)

🚧 View Differences

-=-=-=-=-=-=-

Chapter 1: Early Computers

Return to table of contents

Previous chapter

[Click to view] A picture of The Bombe, from WWII

Early computers were not very good. Many of the first computers used electromechanical switches to store bits, meaning that a little motor would flip a physical switch on to represent a 1 and off to represent a 0. Turing's "Bombe", built in 1939, was an example of just such a computer. This was very unreliable, because moving parts tend to break more easily than stationary parts. Soon, they switched to vacuum tubes, which were more reliable than moving switches, but they had the problem that they would burn out. Burnt-out vacuum tubes had to be replaced regularly, putting serious constraints on how powerful computers could be.

Programming computers back then was a process we would hardly recognize. In the earliest days, a computer program was a board covered in plugs, with a mess of cables plugged into it. A new program would be written by plugging the cables into different sockets to represent different instructions. You might think I'm making this up. I'm not. You can read more about that here:

https://en.wikipedia.org/wiki/Plugboard

Cables and plugs are heavy. With the rise of vacuum-tube computing, they were replaced with what's called a "front panel", which is a board with lights and switches on it. Now, instead of plugging in cables, a program could be entered by toggling switches. A switch turned "on" represented a 1 and "off" represented a 0. In this way, a particular binary number could be represented by a row of switches, and you could toggle in "opcodes" by flipping the switches. An "opcode", or "operation code", is a number representing an instruction for the computer. Read more about front panels here:

https://en.wikipedia.org/wiki/Front_panel

Early on, computer designers converged on the idea of an architecture based on "registers" and "main memory". A "register" is conceptually simple: it's a device that stores a number. This name makes sense if you think about it by analogy to a cash register: a device which stores cash, telling you how much cash is inside it in terms of the number of cents. "Main memory" is slightly more complicated; this is what we now call RAM. It is a system that uses hardware to represent an editable sequence of numbers, each of which has an "address": the first number is at address 0, the second number is at address 1, the third at address 2, and so on. This is handy because, given that a hardware instruction's "opcode" is a number, you can store a program in main memory represented as a sequence of opcodes.

Hardware can't be arbitrarily complicated, so the actual number of opcodes that a computer has instructions for tends to be limited. A particular instruction might have some meaning like "add the value in register A to the value in register B" or "jump to the instruction at such-and-such address in main memory". The computer itself is hardwired to actually do those things when the opcode it is executing equals a specific value. By putting together a sequence of opcodes that encode for various arithmetic operations, conditional checks, and jumps, complicated programs can be assembled from these simple instructions.

Opcodes are hard to remember. I can barely remember phone numbers. How am I supposed to remember a bunch of numbers that represent hardware instructions? It wasn't very long before programmers started making programs to make this easier. You could write a very simple find-and-replace program that would let you use short, memorizable labels to represent the opcodes. Such a program is called an "assembler", because it facilitates "assembling" a program, and the set of labels that is used to generate opcodes with an assembler is called "Assembly language".

Thus, Assembly was the first proper programming language to be widely used. It was a huge step up from manually assembling programs with a front panel. But it still wasn't easy. Assembly is hardware-specific and highly error-prone. It rose to prominence in the 1950s, a time when files were pieces of paper that you kept in a metal cabinet. This brings us to our next chapter:

Challenges of 20th century programming