Est. 1970 Advanced

Assembler (DEC PDP-11)

The assembly language of the DEC PDP-11, whose eight general registers and eight orthogonal addressing modes made it the minicomputer assembler people actually enjoyed writing, and the machine on which Unix and C grew up.

Created by Digital Equipment Corporation; the PDP-11 architecture was designed by Harold McFarland with Gordon Bell, Roger Cady and colleagues

Paradigm Assembly, Imperative, Low-level
Typing None (untyped); each instruction selects byte or word operation, usually with a B suffix such as MOVB
First Appeared 1970
Latest Version No versioned language standard. DEC's assemblers ran from PAL-11A (1970) through PAL-11R (1971) to MACRO-11 (documented for DOS-11 in June 1972), which shipped with every later PDP-11 operating system; the RT-11 V5.7 documentation set on Bitsavers is dated October 1998

PDP-11 assembly language is the assembler of the machine that taught a generation what a computer ought to look like. Eight interchangeable general registers, eight addressing modes that work with any register and almost any instruction, a program counter and stack pointer that are simply two of those registers, and memory-mapped I/O over a single bus: the result was an instruction set that programmers described as pleasant, a word rarely applied to assembly language. It is the language in which the first PDP-11 Unix kernel was written, the language DEC’s own operating systems were built in, and the language whose shape is still visible in the Motorola 68000 and in C.

History and Origins

The machine

DEC shipped the first PDP-11, the PDP-11/20, in 1970. The architecture was designed principally by Harold McFarland, working with Gordon Bell, Roger Cady and others; the team published their design rationale as “A New Architecture for Minicomputers — The DEC PDP-11” at the 1970 AFIPS Spring Joint Computer Conference. The PDP-11 Handbook documenting the 11/20 carries a 1969 copyright, and its chapter on addressing already refers to “PAL-11, the PDP-11 assembler” — the assembly language and the machine arrived together.

The name PAL, Program Assembly Language, was inherited from DEC’s PDP-8 line, but the language underneath it was new. Where the PDP-8 had a single accumulator and a 12-bit word, the PDP-11 offered eight 16-bit general registers and byte addressing, and the assembler’s notation was built to expose that symmetry rather than to hide it.

Three assemblers, one language

DEC’s PDP-11 assemblers came in a sequence, each a superset of the last:

AssemblerDocumentedEnvironmentWhat it added
PAL-11A1970 Handbook, Paper Tape Software SystemPaper tape, 4K words of core, ASR-33Two- or three-pass absolute assembler, optional listing and alphabetical symbol table
PAL-11RPAL-11R Assembler Programmer’s Manual, May 1971DOS-11Relocatable object output, used with the LINK-11 linker and LIBR-11 librarian
MACRO-11DOS MACRO-11 Assembler Programmer’s Manual, June 1972DOS-11, then RT-11, RSX-11, RSTS/EFull macro facility, conditional assembly, program sections

MACRO-11 is what most people mean by “PDP-11 assembly language”. It shipped with every DEC PDP-11 operating system, and its successor on the VAX, VAX MACRO, kept the same statement format and much of the same directive vocabulary. Unix on the PDP-11 went its own way with a smaller assembler called as, structurally similar to DEC’s but with different syntax and far fewer features.

The Unix connection

Dennis Ritchie’s own account is unusually specific. By 1970 the Unix project had earned a new PDP-11 — “among the first of its line delivered by DEC” — and three months passed before the disk arrived. Ritchie wrote a simple PDP-11 assembler in B; Thompson, still waiting for storage, recoded the Unix kernel and some basic commands in PDP-11 assembly language, using 12K bytes of the machine’s 24K for the operating system and the rest as a RAM disk. The essentials of C were complete by early 1973, and the kernel was rewritten in C that summer.

One story about this period is worth correcting because it is repeated so often. C’s ++ and -- operators are frequently said to exist because the PDP-11 had autoincrement and autodecrement addressing. Ritchie explicitly denied it: “This is historically impossible, since there was no PDP-11 when B was developed.” The real influence ran the other way around and was deeper than syntax — the PDP-11’s byte addressing and 16-bit word exposed the inadequacies of B’s single word-sized cell, and pushed Ritchie toward a typed language with char and pointer arithmetic that scaled properly.

The Language

Registers

Eight 16-bit general registers, R0 through R7, with two of them given a hardware role:

RegisterRole
R0–R5General purpose: accumulators, index registers, list pointers
R6 (SP)Hardware stack pointer, used by JSR, traps and interrupts
R7 (PC)Program counter — and a fully general register, addressable by any addressing mode

Making the PC a general register is the single most consequential decision in the design. Immediate operands, absolute addresses and PC-relative addresses are not separate addressing modes; they are ordinary register modes applied to R7. MOV #5,R0 is autoincrement on the PC. That is also why position-independent code is idiomatic rather than exotic on the PDP-11: an ordinary MOV TABLE,R0 assembles to PC-relative form and keeps working wherever the program is loaded.

Addressing modes

Every instruction word carries a six-bit operand field split into a three-bit mode and a three-bit register number, so each mode works with each register:

SyntaxModeEffective operand
RnRegisterThe register itself
@Rn or (Rn)Register deferredMemory at the address in Rn
(Rn)+AutoincrementMemory at Rn, then Rn stepped by 1 or 2
@(Rn)+Autoincrement deferredIndirect through the word Rn points to, then Rn stepped
-(Rn)AutodecrementRn stepped back first, then used as the address
@-(Rn)Autodecrement deferredAs above, one more level of indirection
X(Rn)IndexMemory at X plus Rn, with X in the following word
@X(Rn)Index deferredIndirect through X plus Rn

Autoincrement and autodecrement were the deliberate answer to a weakness Bell identified in earlier minicomputers — the absence of hardware stack support. As he put it in the retrospective, “In the PDP-11, this was solved with the autoincrement/autodecrement addressing mechanism. This solution is unique to the PDP-11 and has proven to be exceptionally useful.”

Combine general registers, general modes and a PC that is just another register, and a small number of opcodes covers an unusual amount of ground. The canonical demonstration is the block copy inner loop:

1
2
LOOP:   MOV     (R1)+,(R2)+     ; copy a word, advance both pointers
        SOB     R0,LOOP         ; decrement R0 and branch if non-zero

Statement format

MACRO-11 statements follow the usual four-field assembler layout, with a semicolon introducing comments and radix 8 by default — a constant written 100 is octal 100, decimal 64, and a decimal constant is written 100. with a trailing point.

1
LABEL:  MOV     #BUFFER,R1      ; label, operator, operands, comment

Directives begin with a dot: .TITLE, .ASCIZ for a zero-terminated string, .WORD and .BYTE for data, .BLKW and .BLKB for reserved storage, .MCALL to pull system-call macros out of the system macro library, .END to close the module. Local labels are numeric with a dollar sign — 1$, 2$ — and are scoped between ordinary labels, which is why PDP-11 listings are not littered with invented names for loop tops.

Instruction set shape

Instructions are one, two or three words and fall into a handful of regular families:

  • Double operand: MOV, CMP, ADD, SUB, BIT, BIC, BIS — source and destination, each with a full addressing mode.
  • Single operand: CLR, INC, DEC, NEG, TST, COM, the rotates and shifts ROL, ROR, ASL, ASR, and SWAB for byte swapping.
  • Byte variants: most of the above take a B suffix — MOVB, CLRB, CMPB — so byte and word code are written the same way.
  • Branches: BR plus the signed, unsigned and simple conditional branches, all PC-relative with an eight-bit offset.
  • Subroutines: JSR and RTS, with any register nominated as the linkage register, so JSR PC,SUBR is a plain call and JSR R5,SUBR is the conventional way to pass an in-line argument list.
  • Traps: EMT and TRAP, the vehicle for operating-system calls, plus BPT and IOT.

Later processors extended the set rather than replacing it: SOB (subtract one and branch) and MARK arrived with the mid-range models, EIS added hardware multiply and divide, and optional floating-point units added their own instruction group.

Code Examples

Hello, world under RT-11

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
        .TITLE  HELLO
        .MCALL  .TTYOUT,.EXIT
HELLO:: MOV     #MSG,R1         ; address of the string
1$:     MOVB    (R1)+,R0        ; next character into R0
        BEQ     DONE            ; zero byte ends the string
        .TTYOUT                 ; monitor call: print R0
        BR      1$
DONE:   .EXIT

MSG:    .ASCIZ  /Hello, world!/
        .END    HELLO

.MCALL tells the assembler which system macros this module uses; .TTYOUT and .EXIT expand to EMT instructions that trap into the RT-11 monitor. Under RT-11 the build and run sequence is .MACRO HELLO, .LINK HELLO, .R HELLO.

Stack and subroutine conventions

1
2
3
4
5
6
SUBR:   MOV     R0,-(SP)        ; push R0 — autodecrement on the stack pointer
        MOV     R1,-(SP)
        ...
        MOV     (SP)+,R1        ; pop in reverse order
        MOV     (SP)+,R0
        RTS     PC              ; return

Push and pop are not instructions. They are the ordinary MOV instruction with autodecrement and autoincrement addressing on R6, which is why the PDP-11 supports arbitrarily many stacks: any register can be a stack pointer, and the same two modes make it one.

Byte counting loop

1
2
3
4
5
6
7
        CLR     R2              ; count := 0
        MOV     #STRING,R1
10$:    TSTB    (R1)+           ; test byte, advance pointer
        BEQ     20$             ; zero terminator?
        INC     R2
        BR      10$
20$:    RTS     PC

Evolution

The instruction set grew outward from the 11/20 for twenty years without ever breaking its shape. Memory management arrived soon after the original design — Bell wrote that it was “extremely embarassing” [sic] that the PDP-11 “had to be redesigned with memory management only two years after writing the paper that outlined the goal of providing increased address space”, and identified the shortage of address bits as the classic unrecoverable design mistake. The mid-range models added SOB, MARK, XOR and the extended and floating instruction sets. The LSI-11 of February 1975 compressed the processor onto four Western Digital LSI chips, and the J-11, developed around 1979, onto two or three, carrying PDP-11 assembly into embedded control applications that the 11/20’s designers never imagined.

The language then propagated in two directions. DEC’s own 32-bit successor, the VAX-11 announced in 1977, kept a PDP-11 compatibility mode in its early processors and gave the VAX an assembler, VAX MACRO, that is recognisably MACRO-11’s descendant. Outside DEC, the PDP-11’s register-and-mode orthogonality became the template other architects copied: Motorola’s 68000 is the case most often cited, and the PDP-11’s convention of mapping device registers into the memory address space, instead of providing separate I/O instructions, became standard practice in much of later microprocessor design.

Current Relevance

DEC stopped building PDP-11s in 1997, three years after selling the system-software rights to Mentec, and the last models of the line — the single-board 11/93 and 11/94 — dated from 1990. But PDP-11 assembly did not stop being written:

  • Industrial and safety-critical installations kept running long past the hardware’s commercial life. In 2013 GE’s Canadian operation was reported to be recruiting a PDP-11 assembly programmer on vintage computing forums to maintain nuclear plant control systems, with the industry’s commitment to the hardware reported as running to 2050.
  • Simulation is mature. SIMH and similar simulators boot original RT-11, RSX-11 and 2.11BSD images, and DEC-era operating system distributions and manuals are archived and freely available.
  • Modern toolchains still target the machine. GCC documents a set of PDP-11 options and the GNU assembler has a PDP-11 dependent-features section — the binutils target is conventionally written pdp11-aout — so it is possible to cross-assemble and cross-compile on a laptop and run the result under simulation or on real hardware.
  • Clone hardware keeps a second community alive. The Soviet-designed Elektronika BK and DVK machines implemented the PDP-11 instruction set, and BK demoscene productions are reportedly still written in PDP-11 assembly.

For anyone learning assembly language today, the PDP-11 remains one of the best teaching architectures in existence: small enough that the whole instruction set fits on a page, regular enough that there are almost no special cases to memorise, and historically central enough that what you learn explains the machines that came after it.

Why It Matters

The PDP-11 is the point where assembly language stopped being a per-machine idiosyncrasy and started being a discipline with a recognisable common shape. Around 600,000 PDP-11s of all models are commonly reported to have been sold, making it one of DEC’s most successful product lines, and a great many of the people who learned to program in the 1970s learned on this instruction set.

Its influence is structural rather than decorative. The idea that registers should be interchangeable, that addressing modes should compose freely with instructions, that the program counter and stack pointer are registers rather than special hardware, that device registers live in the memory map — all of these are PDP-11 arguments that were won so completely they now look like the natural order of things. And because Unix and C were built on this machine, in this language, the PDP-11’s assumptions about bytes, words, pointers and stacks were carried into software that long outlived the hardware and is still running everywhere today.

Timeline

1970
DEC ships the PDP-11/20, the first model of the line. The PDP-11 Handbook that documents it carries a 1969 copyright and already names "PAL-11, the PDP-11 assembler"
1970
Bell, Cady, McFarland, Delagi, O'Loughlin, Noonan and Wulf present "A New Architecture for Minicomputers — The DEC PDP-11" at the AFIPS Spring Joint Computer Conference (Proceedings vol. 36, pp. 657-675)
1970
The Paper Tape Software System ships PAL-11A, a two- or three-pass absolute assembler that runs on a PDP-11 with 4K words of core and an ASR-33 Teletype
1970
Bell Labs takes delivery of one of the first PDP-11s. Dennis Ritchie codes a simple PDP-11 assembler in B, and while the machine still has no disk Ken Thompson recodes the Unix kernel and some basic commands in PDP-11 assembly language, using 12K bytes of the machine's 24K for the operating system and the remainder as a RAM disk
1971
DEC publishes the PAL-11R Assembler Programmer's Manual (DEC-11-ASDB-D, May 1971) for the DOS-11 disk operating system, adding relocatable output and a separate linker
1972
The DOS MACRO-11 Assembler Programmer's Manual (DEC-11-OMACA-A-D) is dated June 1972, introducing the macro assembler that becomes the standard PDP-11 development tool for the next two decades
1973
Ritchie and Thompson rewrite the Unix kernel for the PDP-11 in C during the summer, pushing assembly down to the bootstrap, trap and context-switch layers
1975
The LSI-11 (PDP-11/03), introduced in February, puts the processor on four Western Digital LSI chips and carries the instruction set into embedded and instrument control
1977
Gordon Bell's retrospective "What Have We Learned from the PDP-11?" reports more than 20,000 units sold in ten models over 1970-1975, and calls the machine's shortage of address bits "the biggest (and most common) mistake that can be made in a computer design"
1977
DEC announces the 32-bit VAX-11, whose early processors include a PDP-11 compatibility mode so much existing PDP-11 software keeps running; the mode is reportedly dropped with the first MicroVAX
1979
DEC develops the J-11 ("Jaws-11") two- or three-chip processor, dated to 1979 in DEC-derived timelines; it goes on to power the PDP-11/84 (1985-86) and later models
1990
The single-board PDP-11/93 and PDP-11/94 are introduced; they are the last models of the line
1994
DEC and Mentec announce a PDP-11 software agreement on 29 June, transferring PDP-11 system-software rights to Mentec, which goes on to produce new PDP-11 processors
1997
DEC discontinues PDP-11 production, ending roughly 27 years of manufacturing for the line
2013
GE's Canadian operation recruits a PDP-11 assembly programmer on vintage-computing forums for legacy PDP-11 based control systems used in nuclear power plants; the reporting (The Register, June 2013) describes the industry's commitment to the hardware as running to 2050

Notable Uses & Legacy

Unix at Bell Labs

The first PDP-11 Unix kernel and its basic commands were written by Ken Thompson entirely in PDP-11 assembly language in 1970, and First Edition Unix (manual dated November 1971) was still an assembly-language system. Even after the 1973 C rewrite, the machine-dependent floor of the kernel stayed in assembler.

DEC's own operating systems

RT-11, RSX-11 and RSTS/E were written and maintained in MACRO-11, and shipped it as the system assembler. DEC's user-mode system calls were themselves macros (.TTYOUT, .EXIT and the rest) that expanded into EMT trap instructions.

Laboratory, instrument and process control

The LSI-11 and later Q-bus boards made PDP-11 assembly a standard language for data acquisition and real-time control, where hand-written interrupt service routines were the customary way to meet tight timing budgets. Published head-to-head benchmarks against the compilers of the period are not readily available, so the advantage is best treated as contemporary practice rather than a measured figure.

Nuclear plant control systems

PDP-11-based control systems remained in service in nuclear power plants long after DEC stopped building the hardware. In 2013 GE's Canadian operation was reported to be recruiting a PDP-11 assembly programmer on vintage-computing forums to maintain them, with the industry's commitment to the hardware reported as extending to 2050.

Soviet and Eastern Bloc PDP-11 clones

The SM EVM minicomputers and the Elektronika BK and DVK machines implemented the PDP-11 instruction set, so PDP-11 assembly became the low-level language of a whole parallel computing culture — and is reportedly still the language of the BK demoscene.

Preservation and emulation

SIMH and similar simulators run original PDP-11 operating systems on modern hosts, and the GNU toolchain still covers the architecture — GCC documents PDP-11 options and the GNU assembler has a PDP-11 dependent-features section (the binutils target is conventionally written `pdp11-aout`) — so PDP-11 assembly can still be written, assembled and executed today.

Language Influence

Influenced By

PDP-8

Influenced

Assembler (68K) VAX MACRO C

Running Today

Run examples using the official Docker image:

docker pull
Last updated: