The history of computing could arguably be divided into three eras: that of mainframes, minicomputers, and microcomputers. Minicomputers provided an important bridge between the first mainframes and the ubiquitous micros of today. This is the story of the PDP-11, the most influential and successful minicomputer ever.
In their moment, minicomputers were used in a variety of applications. They served as communications controllers, instrument controllers, large system pre-processors, desk calculators, and real-time data acquisition handlers. But they also laid the foundation for significant hardware architecture advances and contributed greatly to modern operating systems, programming languages, and interactive computing as we know them today.
In today’s world of computing, in which every computer runs some variant of Windows, Mac, or Linux, it’s hard to distinguish between the CPUs underneath the operating system. But there was a time when differences in CPU architecture were a big deal. The PDP-11 helps explain why that was the case.
The PDP-11 was introduced in 1970, a time when most computing was done on expensive GE, CDC, and IBM mainframes that few people had access to. There were no laptops, desktops, or personal computers. Programming was done by only a few companies, mostly in assembly, COBOL, and FORTRAN. Input was done on punched cards, and programs ran in non-interactive batch runs.
Although the first PDP-11 was modest, it laid the groundwork for an invasion of minicomputers that would make a new generation of computers more readily available, essentially creating a revolution in computing. The PDP-11 helped birth the UNIX operating system and the C programming language. It would also greatly influence the next generation of computer architectures. During the 22-year lifespan of the PDP-11—a tenure unheard of by today’s standards—more than 600,000 PDP-11s were sold.
Early PDP-11 models were not overly impressive. The first PDP-11 11/20 cost $20,000, but it shipped with only about 4KB of RAM. It used paper tape as storage and had an ASR-33 teletype printer console that printed 10 characters per second. But it also had an amazing orthogonal 16-bit architecture, eight registers, 65KB of address space, a 1.25 MHz cycle time, and a flexible UNIBUS hardware bus that would support future hardware peripherals. This was a winning combination for its creator, Digital Equipment Corporation.
The initial application for the PDP-11 included real-time hardware control, factory automation, and data processing. As the PDP-11 gained a reputation for flexibility, programmability, and affordability, it saw use in traffic light control systems, the Nike missile defense system, air traffic control, nuclear power plants, Navy pilot training systems, and telecommunications. It also pioneered the word processing and data processing that we now take for granted.
And the PDP-11’s influence is most strikingly evident in the device’s assembly programming.
Assembler programming basics
Before high-level languages such as Python, Java, and Fortran were invented, programming was done in assembly language. Assembly language programming can be done with very little RAM and storage—perfect for the environment of the early days of computing.
Assembly language is a low-level intermediary format that is converted to machine language that can then be run directly by the computer. It is low-level because you are directly manipulating aspects of the computer’s architecture. Simply put, assembly programming moves your data byte by byte through hardware registers and memory. What made programming the PDP-11 different was that the minicomputer’s design was elegant. Every instruction had its place, and every instruction made sense.
A 16-bit address space meant that each register could directly address up to 64KB of RAM, with the top 4K reserved for memory-mapped input and output. Early PDP-11s could address a total of 128KB of RAM using register segments (more on this in a bit). So despite PDP-11 systems coming with only 4KB of RAM, they were still productive through the clever use of early programming techniques.
An assembly language program
It’s easiest to grasp this concept through an example of a simple PDP-11 assembly language program, which we’ll go through below. Keywords that start with a “.” are directives to the assembler.
.globl exports a label as a symbol to the linker for use by the operating system.
.text defines the start of the code segment.
.data defines the start of a separate data segment. Keywords ending with a “:” are labels. Assembly programming uses labels to symbolically address memory. (Note: With the PDP-11 jargon and coding to come, any text after / is a comment.)
|.globl _main||Export label _main as an entry point for the operating system to use|
|.text||Start of instruction segment where read-only code lives|
|_main: MOV VAL1, R0||Copy the word value at memory location VAL1 into register 0|
|ADD $10, R0||Add 10 to the value in register 0|
|MOV R0, VAL1||Copy the value in register 0 to the memory location VAL1|
|.data||Start of data segment where read/writable data lives|
|VAL1: .word $100||Reserve 2 bytes of storage to hold Val1, initialized to 100|
Although numeric values can be used for memory addresses, the use of labels instead of hard-coded addresses makes it easier to program and makes the code relocatable in memory. This gives the operating system flexibility when running the code, ensuring each program is fast and efficient.
The .data assembler directive puts the data in a memory segment that’s both readable and writable. The memory segment for code is read-only to prevent programming errors from corrupting the program and causing crashes. This separation of instructions from data on the PDP-11 is called “split instruction and data.” In addition to adding stability, this feature also doubles the address space by enabling 64KB for code and 64KB for data—this was considered quite an innovation at the time. Accordingly, Intel’s X86 microcomputers later made extensive use of segments.