Version1

Recently, I set out to run 8080 BASIC VER 1.0 on an IMSAI 8080 and a Teletype Model 33-ASR. This page documents my journey.

November 2023

Altair BASIC

The BASIC programming language was invented at Dartmouth University in the 1960s. Thomas Kurtz and John Kemeny designed it as an accessible, short turn-around programming experience for novice users of the Dartmouth Time-Share System. When microcomputers were introduced a decade later, including the MITS Altair 8800, the race was on to provide higher level languages that got users beyond toggling machine code programs into the front panel. (Although even this minimal user interface resulted in some fantastic creative coding, such as Steve Dompier's Music of a Sort.)

In the often-told tale, Bill Gates and Paul Allen saw an opportunity when the Altair made the front page of the January 1975 issue of Popular Electronics. They wrote a version of BASIC for the 8080 microprocessor in a stint of furious programming that lasted several weeks while Gates was still a student at Harvard. A classmate, Monte Davidoff, wrote the floating point math package. Allen then flew to MITS in Albuquerque, New Mexico with a paper tape copy to demonstrate it to the Altair's inventor, Ed Roberts. I can imagine that Alan Turing would have been pleased when the program ran on actual hardware. Until then, the young programmers had tested their code exclusively on an emulator Allen had written for the DEC PDP-10 in Harvard's Aiden Computer Laboratory.

That first version is 8080 BASIC VER 1.0, and it was written in early 1975. By the end of the year, Allen and Gates were both in Albuquerque, improving their BASIC and starting a new company, Micro-Soft.

To run 8080 BASIC VER 1.0, I wanted to recreate the early user experience: toggling a loader program into the front panel and loading the program by paper punch tape using a teletype as the console. In fact, it would represent the earliest experience before there were even any users.

Software

First, I needed to make a punch tape of the program. Several versions of early BASIC are available online as binary files. I downloaded a copy from Mike Douglas' DeRamp.com site. The VER 1.0 tape is simply a dump of the executable binary with a sync byte (0x6A) at the start -- no checksums or other error checks. The binary file is actually 4509 bytes (4429 bytes plus some nulls before and after the code). At ten bytes per inch, it's about 37.5 feet of paper punch tape. Punching and reading the tape takes about seven and a half minutes with the Teletype's 110 baud interface. (That's 10 characters or bytes per second because two stop bits are used in addition to the start bit.)

I punched the tape using the ASR-33 connected to a Raspberry Pi ttyAMA0 serial port. A short script adjusts the stty settings of the terminal to send the binary file. But first, I needed to disable the ASR-33's tape-on and tape-off functions. Currently, when the teleprinter receives a CNTL-R (0x12) or CNTL-T (0x14) character, it stops or starts the tape punch. This is all right (but somewhat annoying) behavior when reading a tape, but obviously it will interfere with punching a tape. To disable the function, two small clips are installed at the back of the punch code bars to fix the sensing levers.

0cb3a86b69e0a7b0 502c43d7005382f4 e807c5d3529e399b 4fd9bb21e55a4824

With the tabs installed, we can verify that the reperforator now correctly punches 0x12 and 0x14. Punching the tape uses the following short script, which sets the terminal in a "raw" state (no input or output processing) and generates more nulls on either side of the file for easier operation in the tape reader:

#!/bin/bash
# punch binary file
# must run "3" or equivalent after
# start and stop the punch

function echo_null {
    for i in {0..40}
    do
	echo -ne "\000"
    done
    }

if [ -f "$1" ]; then
    stty raw
    stty pass8
    stty istrip
    echo_null
    cat $1
    echo_null
    echo_null
    echo_null
else
    echo "pbf filename"
fi

The nulls at the end enable the operator to stop the punch tape before the script ends. One of the challenges after running this script is the state of the terminal input. The teletype sends output in 7E2, which will be interpreted as escape characters by the Linux shell. I run a short script that returns the terminal to a normal state. The script has an alias "3", which can be interpreted correctly by the shell because the (even) parity bit won't be set.

Below is a picture of the punch tape of 8080 BASIC VER 1.0. This isn't an exact copy of the tape that Paul Allen took to MITS in 1975. Instead, it's been patched to use a later MITS serial interface, the 88-2SIO. I'll cover a few of the details below.

e8fcfbf91214cfa2

Hardware

I wanted to get as close as possible to the user experience in 1975. An IMSAI 8080 is the nearest machine I have to the MITS Altair 8800. [1] The IMSAI was the first "clone" microcomputer and was released about a year after its rival from MITS. The IMSAI faithfully reproduced the Altair bus (later to become the S-100 standard) and basic design, including the front panel display and toggle switches. I would be able to toggle in the short loader program and load BASIC from the punch tape.

This particular IMSAI is configured with 10 boards in the backplane: 5 memory (four 8K RAM boards and one 32K), two serial boards (the Processor Tech 3P+S and an IMSAI SIO-2), a disk controller (Tarbell) and of course the CPU board. Oh, and an extender card, plus the front panel. It normally runs CP/M 1.4 off a pair of 8" disk drives and is connected to an ADM-3A terminal. This would have been a pretty sweet machine in 1977 or 1978. Since the objective of the exercise is to run 8080 BASIC VER 1.0 in as close to the original form, I had to strip down the IMSAI to just a basic unit: CPU, RAM, and serial while using the Teletype as my console. Before tearing down my system, I checked that it was working as configured by booting CP/M and running Microsoft CP/M BASIC version 4.51.

4241a8ed8c5b1626 e116372442078564 7fcca458a6721346 1eaa0289df4cffcf

I pulled all but one of the 8K RAM boards and the disk controller. The next step was to configure the serial board, and I had a choice between the Processor Tech 3P+S and the IMSAI SIO-2. I had to configure one of them to act like the MITS 88-2SIO (or MITS 88-SIO REV. 1) serial board in order to run 8080 BASIC VER 1.0. This is where the specifics of handling serial communication in an S-100 system gets complicated.

Altair systems use the I/O port features of the 8080 microprocessor. There are 255 reserved I/O ports with addresses 00-FF. Different devices: serial interfaces, parallel cards, and disk subsystems, use unique port values or a range of values. These values are determined by the hardware through an addressing scheme. The 8080 signals that it is reading off of the data bus using P DBIN line at the same time sINP (for input) or sOUT (for output) signals to the peripherals an I/O instruction read or write. The processor places the I/O port on the address bus, duplicating the 8-bit I/O address value in the high and low ranges of 16-bit value. Activated by P DBIN and sINP or sOUT, each peripheral card decodes the I/O value, responding if it corresponds to the selected value. The earliest MITS serial card (88-SIO REV. 0) used ports 00h and 01h. A later revision used ports 10h and 11h.

Notice that two ports are required for the serial card. In the MITS board, the lower one is the STATUS port, which communicates with the card to determine whether the transmit buffer is empty (TBE) and ready for a byte to be sent, or if a data byte has been read in (read data available, or RDA). Other status indicators typical of EIA interfaces can also be sent and received, like CTS and RTS values. The higher port, DATA, is reserved for sending and receiving bytes. A further complication is that the STATUS byte can use different bits to indicate each signal. MITS initially used the least significant bit in the STATUS byte, D0, as the RDA status bit and D7 for TBE. Later these were changed to D0 and D1. More confusingly, activity in each case was originally signaled by a zero value, which MITS later changed to a more conventional "active high" signal in the REV 1 board. These hardware details are encoded directly into the BASIC program code, so the hardware I was using had to be made to work with the software! The problem of interfacing hardware to software like this was solved later by Gary Kildall when he invented the BIOS -- all of the I/O details were placed there, freeing his software (the CP/M operating system and its software) using this new abstraction layer.

To deal with the interfacing situation, manufacturers adopted either their own standard or provided many options for their serial boards to mimic other manufacturers' cards. In the case of my IMSAI SIO-2, it cannot be used as a MITS 88-SIO without modifying the hardware. The IMSAI board reverses the order of the status and data ports, using the lower one for data and the upper port for status -- the opposite of the MITS 88-SIO board. However, the Processor Technology 3P+S (3 parallel and 1 serial interface) can be configured to mimic at least the 88-SIO REV 1 board (it also indicates RDA and TBE by a one, not a zero). Below is a picture of the 3P+S board and a few of the many jumper settings. In addition to switching the ports and RDA / TBE bits, I had to configure it for 110 baud.

f3702ab885fc6946 bac382b216fd21bd 7c2a13c6265e6d6c

Troubleshooting the serial connection took some time, but eventually I had the IMSAI reading to and from the Teletype. There were the usual detours: discovering that my Solid State Music 8K RAM board was giving errors in the $1400 range of addresses (I'll have to sort that out later) and that I was addressing the wrong TBE bit on the 3P+S card. I ended up toggling through about half of the 4K program from the front panel, checking every byte against the paper tape, and in the process wearing out the IMSAI's EXAMINE toggle switch.

Finally, I managed to load BASIC successfully and was greeted by the canonical message:

MEMSIZ?

This was the first text that Paul Allen saw when he loaded BASIC on the Altair at MITS in 1975!

d71e7b003e18286e

8080 BASIC VER 1.0 uses the same READY message as a prompt that Dartmouth BASIC used. Later, this was shortened by Microsoft to OK.

User experience

What is it like to run this early version of microcomputer BASIC? How was it similar to or different from time-share systems of the mid-1970s? The process begins at the front panel, where the user toggles in a 20-byte loader into memory.

26 00 31 12 18 DB 10 0F
D0 DB 11 77 23 D6 6A C0
6F C9 02 18

This program reads from the serial port and stores the bytes into memory.

740dd0bf5f60aa66 8b208e18663a1323

The paper tape of 8080 BASIC VER 1.0 is mostly a binary dump of the program. There are no checksums and secondary loaders that would come in later versions. The paper tape has a series of NULL bytes that serve as a leader. The byte A6h marks the beginning of the code (the "sync" byte) and the next few bytes are a jump command to the cold start routine. BASIC loads at address $0000.

This loader program is toggled in at address $1800, well above what will be read in from the tape even with some trailing NULLs. Setting the address back to $1800, the user loads and starts the punch tape, then toggles the RUN switch. The initial bytes are read into memory, and then replaced by the program with the sync byte is read. It takes about seven and a half minutes at 10 bytes per second to load BASIC. When the tape finishes, the user toggles RESET on the front panel, which stops the loader and sets the machine's address to $0000, then RUN. If all goes well, the cold start routine begins with MEMSIZ? and other queries. Hitting return on the first question allows BASIC to use the full free memory for program and variable storage. There is more user space if the trigonometric function routines are not loaded.

MEMSIZ?
WANT SIN-COS-ATN?
2000 BYTES FREE

8080 BASIC VER 1.0

READY

I started off by writing the recent meme HELLORLD! program (a take on Kernighan and Ritchie's Hello World).

a34df48e5961f588

Then I tried something a little more ambitious: a Mandelbrot program. It is not a fast program in BASIC under any circumstances, but (without rigorous benchmarking) the program was markedly slower than in later versions of Microsoft BASIC and HP timeshare BASIC. Those floating point routines of Davidoff's probably needed some refinement. (Unlike Gates, Davidoff did graduate from Harvard in 1978.)

e44480cff41c1fd7 308d367a2c79e63e 69b60c86379e9500 1a3b3e133c5c2d09 1910cb34302d4bec

The interpreter was also finicky about the FOR...NEXT loops. The program I've used in the past iterates using a loop, which is broken if the divergence criteria is exceeded. That program wouldn't run, so I implemented a counter in the code. The other significant difference came in printing. In the past, I've generated Mandelbrot sets using a scheme that prints a number (or character) corresponding to the iteration that the calculation diverged at. It is the inverse of the scheme shown in the images above, where a space indicates a complex value in the set. That turned out to be impossible in 8080 BASIC VER 1.0 because expressions (numbers) print with a space on both sides. Thus, a command like

PRINT I;

creates the output seen here:

d1338b37082ac68c

The output also had to be a single character. There is no CHR$ command in this version of BASIC.

Hacking BASIC

I wanted to modify the output routines in BASIC so I could print a Mandelbrot image using the iteration number as a "colormap". This would require getting rid of the spaces when an expression is printed. So, I spent a little time disassembling some of the BASIC machine code. Looking for a space character in the binary file (on a modern machine) I identified a promising sequence where the byte 20h is loaded into the accumulator and then sent to the output port. Here's the code:

print_space:

03D2	3E 20		MVI A, ' '	; this is the trailing space for expressions

outchar:

03D4	F5 		PUSH PSW
03D5	DB 10		IN 10
	E6 02		ANI 02		; check TBE
	CA D5 03	JZ 03D5		; jump back until transmit ready
	F1		POP PSW
	D3 11		OUT 11		; send character
	3A BD 01	LDA 01BD	; cursor location?
	3C		INR A
	32 BD 01	STA 01BD
03E6	FE 46		CPI 46		; this is 70, no? *** 
	CA 8D 06	JZ 068D		; jump to newline, return from there
	C9 		RET	

I patched BASIC by loading it and running it through the cold start. Then I stopped the machine and replaced the byte at $03D3 with a 00h instead of 20h. I hit reset and run, which took BASIC through the warm start ("READY") and ran my Mandelbrot program. It was close! I had gotten rid of the spaces, but the output was unexpectedly broken up into shorter lines.

d8fee9c464f4567f

A hint comes a little further down in the code in what appears to be a character output routine. After writing a byte to the serial output (Teletype), the program increases some variable and then checks whether it has a value of 70 (CPI 46h). This looks like it is testing for a column number which is close to the maximum value for an ASR-33 (72). Looking further down in the code that it jumps to ($068D) it sends a carriage return and new line to the teleprinter.

newline:

068D	F5		PUSH PSW
	AF		XRA A	; zero out cursor location?
	32 BD 01	STA 01BD 
	3E 0D		LDA '\r'
	DF		RST 3	; out_char routine
	3E 0A		LDA '\n'
	DF 		RST 3
	AF		XRA A
	32 BD 01	STA 01BD
	F1		POP PSW
	C9		RET

Replacing 46h with FFh at $03E7 did get rid of the line truncation when the Mandelbrot program ran. Here are some of the results of slow Mandelbrot calculations in 8080 BASIC VER 1.0.

f877c730d4ffb3db c0fdc813ea5b7555 f8a131401d24a7e4

Interestingly, that RST 3 instruction jumps to $0018 and executes the following:

RST 3 out_char:

0018	E6 7F		ANI 7F	; strip top (parity) bit
	C3 D4 03	JMP 03D4	; outchar routine
	00 
	00
	00

It strips the top (parity) bit and jumps to the print routine at $03D4 we looked at above. I'm not sure why it seems to zero out the cursor location both before and after the carriage return and newline characters are sent. The high bit seems to be used in the last character of a printed string, but strings are also terminated by a NULL.

What I learned

It's interesting to see the influence of Dartmouth BASIC in 8080 BASIC VER 1.0. The Dartmouth command SCRATCH would later become NEW and we see READY instead of OK. Gates' innovation with BASIC, and later with DOS (and possibly Windows), was seeing an opportunity to bring an existing idea or product to a new, emerging market. It was a successful strategy with microcomputer BASIC and wildly successful for MS-DOS.

8080 BASIC VER 1.0 works, but it is limited. The interpreter implements only a fraction of the BASIC commands that were available on larger systems. A comparison of 4K and 8K Altair BASIC published later by MITS appears below (from the Age of Altair product catalog),

eefba0d26ee54f21

There is no string manipulation in the 4K version, it has only six decimal digits of precision in the floating point routines, there are no subroutines, and only a small subset of mathematical functions. History records that in in early 1976 Bill Gates published his Open Letter to Hobbyists declaiming against the practice of making copies of Altair BASIC without paying for them. This narrative may lack some context. Early Altair BASIC, which was priced at $150 (nearly $900 in 2023 dollars), seems to be impractical for any serious programming work. The later 8K BASIC would be far more powerful and potentially important for writing small software packages and products, but could this earliest version have been little more than a curiosity to be passed around and played with a little? It seems hardly worth the investment that MITS was asking, although they did sell it for a lower price as a bundle with their memory card. Is our perspective of this time and especially Gates' "Open Letter" accurate or complete?

Perhaps reinforcing this point, I've had limited success saving and restoring programs. I can send the program to punch tape simply by listing it while the Teletype's punch is on. Reading the program back in is more difficult. While the reader functions identically to typing in text, BASIC requires some time after entering a line to process it. Because the tape reader isn't pausing like a user, characters can be missed, especially the line numbers. I can probably prepare a tape beforehand and include NULL characters after each return to give BASIC some time to process the input, but I can't save a program from BASIC that can be read back in. (I bet I could write a little machine language program that processed a BASIC output tape, added the NULL characters, though.)

Altair BASIC timeline

Reading through early MITS publications and documentation to learn more about the development of BASIC, especially in 1975, it is clear that Gates, Allen, and Davidoff worked quickly to develop 8K BASIC and improved 4K versions. There is an obvious gap between what was being written about BASIC in MITS literature, including their newsletter, Computer Notes, and what was being sold. The pricing took time to develop, too. In the April, 1975 issue of Computer Notes, Altair BASIC is listed at $500, but $75 when purchased with an Altair, 8K memory, and either a serial I/O board or an audio-cassette interface. That "unbundled" price would adjust downward significantly over the course of the year. The prices quoted earlier appear in the August 1975 issue of Computer Notes and BASIC doesn't appear to have even shipped to users before late June, 1975. From the July, 1975 Computer Notes issue:

Q&A - Altair BASIC
Q. When will the different versions of BASIC be available?
A. The 4K and 8K versions are scheduled to be shipped starting June 23, and the Extended BASIC in late July.

This also appears to be when Microsoft BASIC adopted the command NEW and the prompt OK. Microsoft's history site claims that BASIC officially shipped as version 2.0 in both 4K and 8K editions on July 1, 1975.

There are some more details about BASIC in the August 1975 issue of Computer Notes. It describes the upcoming features of version 3.0 and the upgrade cost to users of the earlier version:

GENERAL SOFTWARE
By Paul Allen

Q. Do you know yet how fast the improved floating point routines are?
A. Yes. Version 3.0 of Altair BASIC will be about twice as fast as version 2.0. A FOR I = I T0 10,000: NEXT loop takes about 14 seconds. A floating multiply takes about 5 milliseconds and a divide takes about 8 milliseconds. These last two times may vary significantly depending on the operands.

Q. Any other differences in 3.0?
A. Yes, the 8K version is not only faster, it is also about 100 bytes shorter, due to many long hours spent by our programmers optimizing the assembly code. No new features are present in 3.0. The 4K 3.0 is the same size as 4K 2.0 but it is two times faster.

Q. When will 3.0 be shipped to customers?
A. In early August. Customers who have already received 2.0 may obtain 3.0 for a copying charge of $15.

That issue also announces the "July Software Contest Winners," in which Gates writes that John Klein's second place Blackjack program was "one of the first BASIC programs written specifically for Altair BASIC and it uses some of the nice features of 8K BASIC."

By the November / December 1975 issue of Computer Notes, Gates writes in an article called The Status of BASIC, "If anyone is using 2.0, I encourage them to upgrade to 3.2, mainly because Version 3 BASICs are so much faster than Version 2. There is also this interesting statement:

If anyone is using BASIC version 1.1, you have a copy of a tape that was stolen back in March. No customers were ever shipped 1.1, as it was experimental and is full of bugs!

Paper tape images archived online [2] provide some more milestones for the Altair BASIC development timeline:

October 5, 1975 -- 8K BASIC REV 3.0
December 7, 1975 -- ALTAIR FOUR K BASIC VER 3.2
December 22, 1975 -- EXT BASIC VER 3.2

As far as I can tell, no versions of Altair BASIC version 2.0 survive in online archives. That fact could reflect the better functionality and speed of version 3.

Stolen BASIC

How and when a copy of Gates and Allen's BASIC was stolen and distributed is described in a few places, including by Stephen Manes and Paul Andrew [3] and an article recounting the story by John Markoff [4]. In some histories of the early microcomputer era, Gates' open letter to hobbyists seems to refer to the June 1975 meeting of the Bay Area Homebrew Computer Club. At the meeting, 50 copies of Altair BASIC on paper tape appeared in a cardboard box. Someone took a copy of Altair BASIC when the "MITS Mobile" came through California in May and early June, as reported in the July, 1975 issue of Computer Notes. "Hundreds of people have seen ALTAIR BASIC demonstrated at the MITS-MOBILE Computer Caravan." Markoff puts the time and place of the theft as Rickey's Hyatt House in Palo Alto, where MITS had set up their traveling demonstration show.

Given the timing of Gates' letter, though, he must be referring to a broader practice of copying and sharing BASIC than the specific events of that past summer. He is clearly referring to the later and far more functional versions of 8K BASIC. The copies in the cardboard box at the Homebrew Computer Club were presumably copies of what would be Version 2 -- the earliest public release of Altair BASIC.

Conclusions

To understand the capabilities, limitations, and bugs of Altair BASIC VER 1.0, you have to appreciate that it demonstrated a feasibility more than a finished product. As its history shows, Altair BASIC would be refined quickly, and at an impressive pace considering the small team behind it. What would become Microsoft BASIC, encoded in the ROMs of millions of home computers over the next decade, evolved into fairly powerful implementations, up to version 3.2 in 8K and extended 12K, and disk BASIC, in under a year. Version 2.0 was the first officially released version. Its features, and certainly its price, were confusing at first as Roberts at MITS, and Gates and Allen at their fledgling company, continued to improvise in this new and changing market.

Notes and references

(still working on this...)

  1. Later, I built a replica Altair 8800. See Altair8800c.
  2. http://bitsavers.trailing-edge.com/bits/MITS/
  3. Manes, Stephen and Andrews, Paul. Gates: How Microsoft's mogul reinvented an industry--and made himself the richest man in America. New York: Doubleday, 1993.
  4. Markoff, John. A Tale of the Tape From the Days When It Was Still Micro Soft. New York Times, September 18, 2000.