When the Altair 8800 microcomputer was announce by MITS in the January 1975 issue of Popular Electronics, it excited the dreams of two young men in Cambridge, Massachusetts, Paul Allen and Bill Gates. These two had long wanted to write a version of the BASIC language in which they had first learned to program several years earlier in High school, and here was a system for which they could do that.
How do you write a program for a computer which you don’t have? You use another computer and write a program to write your programs with. Paul Allen had already done this once, for an earlier project called Traf-o-Data which the two had created. To understand how it worked, we’ll first look at the computer on which they first developed their skills at system design and programming, the Digital Equipment Corporation PDP-101.
The PDP-102 was the second generation of a line of mainframe computers from DEC, introduced in 1967 as a follow-on to the PDP-6 using the technology invented for the PDP-7 minicomputer. These systems arose in a time before the ubiquitous fixed size 8-bit byte, following an older standard with 36 bits per word in memory or on tape or disk media. Here, bytes were defined by the programmer for specific uses, and could be anywhere from 1 to 36 bits long as needed.
A feature of the PDP-10 which is important for our story has to do with the machine language of the central processor, which divides the 36 bit word3 up into several meaningful portions: A 9 bit instruction specifying an operation (“opcode”), 4 bits to select a register destination for the operation (“AC”), 1 bit to indicate whether the operation takes place on the data pointed to by the instruction or instead on data pointed to by the address pointed to by the instruction (“indirect”), 4 bits to select a register holding part of the address on which the instruction will operate (“index”), and 18 bits specifying part or all of the address or data on which the instruction will operate (“address”).
Now 9 bits can specify up to 512 different possible instructions, but the PDP-10 only defines a few more than 360.4 In most processors, that would be the end of the discussion, but DEC did things differently: They created a way for the otherwise unused instructions to be available to the programmer or the operating system, and called them UUOs.5 There were 2 classes of UUOs: “Monitor UUOs”, defined as opcodes 040-077,6 are used by the operating system7 to implement complex system calls such as opening files, moving data between peripherals, etc., while “user UUOs” (opcodes 001-037) were available to any programmer as a fast way to call routines in her program in the same way system calls worked.8
The monitor UUOs are assigned names like OPEN, CLOSE, INPUT, and so on, so that the programmer can simply use them like other instruction mnemonics like MOVE or ADD, but the user UUOs do not have names since they are intended to be program specific. The assembler language program, called Macro-10, provides a way to give a name to an operation, and will use that name just like the predefined mnemonics provided by DEC.
Assembler programs have existed since the early days of computing, as a way to eliminate programmer errors introduced by translating instructions into numerical representations by hand. They originated as simple tables of substitutions, but grew in capabilities as experience showed the possibilities for computers to manipulate text files. The most important such capability was the invention of “macroinstructions”, a way for the programmer to define a group of instructions which differed in specific ways which could be defined so that the assembler program could build a program more efficiently. An example will make this more clear.
The idea of a macro is to give a name to a block of text. Then when we mention the name, the corresponding text appears in the program and is treated by the assembler as if it were there all along. Our specific example is9
MOVEI 2,15 IDPB 2,1 MOVEI 2,12 IDPB 2,1 MOVEI 2,0 IPDB 2,1
This code takes a byte pointer in location A which points to the end of a text string, and adds an ASCII carriage return (octal 15 = ^M = CR), line feed (octal 12 = ^J = LF), and a null character (octal 0 = ^@ = NUL) to the end of the string.
Writing these 6 lines of code repeatedly throughout a program would be tiresome, so we define a macro to do this for us:
DEFINE ACRLF < MOVEI 2,15 IDPB 2,1 MOVEI 2,12 IDPB 2,1 MOVEI 2,0 IPDB 2,1 >;End of ACRLF
We can now use ACRLF to “Add a CR and LF” anywhere in our program that we might type an instruction.
Suppose we want to be able to put a byte from any AC, not just 2, into any string pointed to by a byte pointer, not just AC 1. In that case, we define our macro to take arguments, which will be substituted for by the assembler program when the macro is used:
DEFINE ACRLF (ACC,BYP) < MOVEI ACC,15 IDPB ACC,BYP MOVEI ACC,12 IDPB ACC,BYP MOVEI ACC,0 IPDB ACC,BYP >;End of ACRLF
Now, to use our macro to pad the string pointed to by PTR-1(Y) using the AC which we have named C in our program:
which will expand to (that is, the following code will appear to the assembler as if we had typed it in directly)
MOVEI C,15 IDPB C,PTR-1(Y) MOVEI C,12 IDPB C,PTR-1(Y) MOVEI C,0 IPDB C,PTR-1(Y)
Why is this important?
Paul Allen’s 8008 Simulator Program
Years before Microsoft, Paul Allen and Bill Gates started another company called Traf-o-Data, to build a traffic counter using the Intel 8008 microprocessor chip. While the Traf-o-Data hardware was being designed an built, Paul wanted to begin programming the 8008 but had no computer for the purpose, so he wrote a PDP-10 program to simulate the chip instead.10
The way it worked was simple. Intel published a data sheet which described what each instruction did with every 8 bit byte decoded. Paul wrote routines to perform the same operations on data in the PDP-10, storing the 8 bits of the 8008’s words in the 36 bits of the PDP-10’s. He defined UUOs to call these routines, and wrote macros which looked like the 8008 instructions published by Intel but expanded into his PDP-10 UUOs when assembled with Macro-10. Now Paul and Bill could write 8008 code for their Traf-o-Data hardware and test the resulting program using a PDP-10!
Paul had always wanted to write a version of BASIC, but Bill pointed out the inadequacy of the 8008 for Paul’s ideas. Not to be put off, Paul kept watching the news of the electronics world, and when Intel brought the 8080 he noted to Bill that all of the objections to the 8008 had been addressed in the new chip. Bill responded that no one build a computer which used the 8080. That was the state of things when the January 1975 issue of Popular Electronics hit the news stands in mid-December 1974, announcing the Altair 8800.
Paul and Bill were excited to learn that although the PE article said that BASIC was available for the new computer, no such program existed yet. Paul revised his 8008 simulator for the 8080 instruction set, and they began writing a version of BASIC using the new simulator program to test their code.
The 8080 simulator still exists on DECtapes belonging to Paul Allen’s estate. The contents of these tapes were copied onto the XKL Toad-1 which Paul purchased in 1997, and later onto the DECSYSTEM-2065 on which he debugged the early version of Altair BASIC which also resides on those DECtapes and which he demonstrated for Leslie Stahl on “60 Minutes” in 2011.
The following is a typeout of a short session on the DECsystem-10 at LCM+L with the 8080 simulator running an early version of Altair BASIC:
* * Authorized users only - All activity is monitored. * To request access visit https://livingcomputers.org * Visit https://wiki.livingcomputers.org for documentation. * * Use ssh email@example.com to connect. * * CTRL-] quit to return to the menu * PDPplanet DECsystem-10 #3530 TOPS-10 v7.04 .login alderson Job 16 PDPplanet DECsystem-10 TTY7 Password: [LGNLAS Last access to [20,20] succeeded on 24-Mar-120:12:38:55] 14:09 24-Mar-120 Tuesday .run tbasic[20,10] * SIM-8080 EXECUTION * MEMORY SIZE? 8192 STRING SPACE? 1024 WANT SIN-COS-TAN-ATN? Y 1276 BYTES FREE ALTAIR BASIC VERSION 1.1 [EIGHT-K VERSION] OK PRINT 2+2 4 OK 10 FOR I=0 TO 10 20 PRINT I 30 NEXT I 40 END LIST 10 FOR I=0 TO 10 20 PRINT I 30 NEXT I 40 END OK RUN 0 1 2 3 4 5 6 7 8 9 10 OK ^C .kjob Job 16 User ALDERSON [20,20] Logged-off TTY7 at 14:11:36 on 24-Mar-120 Runtime: 0:00:01, KCS:40, Connect time: 0:02:04 Disk Reads:173, Writes:6, Blocks saved:80570
Descendants of this simulator were used at Microsoft to write a number of products to the end of the 1980s, when microcomputers finally became powerful enough to host sophisticated development environments.
- Digital Equipment Corporation was usually called DEC, and we will use that from now on.
- In what follows, we will refer only to the PDP-10, but everything we say will apply to the PDP-6 as well unless specifically stated otherwise.
- Bear with me: It will be clear in a moment why we have to get this technical.
- Different models have slightly different instruction counts as features were added to later systems.
- In the earliest documentation, these were called “UnUsed Operations”. Later, this was amended to “Unimplemented User Operations”, to make them sound less ad hoc.
- Numbers here are in base 8 (octal), because 3 bits gives values between 0 and 7 inclusive.
- Here, “the operating system” refers to the original monitor called Tops-10, as well as monitors written elsewhere such as ITS at the MIT AL Lab. Other operating systems such as TENEX and its descendant TOPS-20 use a different UUO for the same purpose.
- In the MM mail system for the TENEX and TOPS-20 operating systems, several complex parsers for mail headers and other behind the scenes processes are implemented using UUOs like this.
- The examples and text are adapted from the excellent Introduction to DECSYSTEM-20 Assembly Language Programming by Ralph E. Gorin (Digital Press, 1981).
- Adapted and condensed from Paul Allen’s autobiography, Idea Man (Portfolio, 2011).