45

According to his 1984 interview with Byte magazine, Steve Wozniak created the BASIC for the Apple 1 computer before he actually built the computer:

I sat down and wrote the BASIC first, and that took a lot more time than the computer design. Once it was written, I had to build the computer.

How was this actually done?

  • Was this simply a high-level concept, actual machine code for the 6502, or an actual implementation on a different system?
  • Was the development only on paper, or was a host computer involved (possibly at his work at HP)?
  • Did he test it elsewhere before putting it on the Apple 1?

This question is only about what Wozniak did. The question never was about whether hand-assembly is possible. In all revisions of the question, hand-assembly was always the first option in bullet #2.

Examples of others performing hand assembly does not answer whether Woz did it. Indeed, I have hand-assembled programs myself, so I have first-hand experience that it is possible.

Please stop using this question as a forum on hand assembly. This question is about what Wozniak did in practice.

DrSheldon
  • 15,979
  • 5
  • 49
  • 113
  • 1
    This sounds somehow as if you think writing a program as well structured and modularized as a BASIC is by hand is impossible? – Raffzahn Feb 12 '21 at 03:48
  • 2
    @Raffzahn: I've altered the question, because you seem fixated on the word "possible". I was not implying that it is impossible, as I have done hand assembly myself. It is not difficult to translate opcodes, but my personal experience is that it is all too easy to mis-count at least one branch displacement in a significant portion of code. Thus, I am all the more surprised that a significant amount of untested code would work on the first try. – DrSheldon Feb 12 '21 at 05:38
  • 1
    Who says the code did run right away, and no testing needed? I would assume there was some debugging needed as well, like with any other software. Noone is perfect, errors come when in machine language as much as in Assembly. But in either case well prepared structure will help minimizing them ahead of punching in bytes. – Raffzahn Feb 12 '21 at 05:59
  • 12
    Once upon a time, getting started on the software before you had a computer was the normal way to proceed. And you had to hand-assemble the first assembler. It was uphill in both directions. – dave Feb 12 '21 at 12:39
  • 12
    Long before that, Ada Lovelace was writing code for Babbage's analytical engine which was never even built, and there weren't any other computers available at the time either. It's not that far-fetched. – Darrel Hoffman Feb 12 '21 at 14:30
  • 2
    @another-dave It is quite common in embedded applications as well to start writing the firmware before the hardware is finalized. – Omar and Lorraine Feb 12 '21 at 19:05
  • On the other hand, since I'm not as smart as Woz, I'd have probably started with an assembler. – dave Feb 12 '21 at 19:30
  • 3
    @another-dave: You'd have a development bootstrapping problem. The assembler itself needs to be assembled, whether by hand or by another assembler, or needs to be written in a language like BASIC. In the BYTE interview, Woz says he originally wanted FORTRAN for his computer, but when someone introduced him to BASIC, he realized that it was a better choice. Makes me wonder how things would have turned out if he had seen FORTH. – DrSheldon Feb 12 '21 at 19:39
  • I mean, I'd have written an assembler so that I had an assembler to write BASIC. I understand that "assembler v0" would have to be hand-assembled; then I'd use that to write "assembler v1".... but this seems more pleasant than hand-assembling BASIC. – dave Feb 12 '21 at 21:36
  • @DrSheldon Another-Dave isn't so off here. I guess I would have thought about going the same way and writing an assembler first. It should be possible to write an assembler, using the original cross assembler syntax, in less than a KiB, including an editor. But that would add a new problem as there was no way to handle files or print them out. So the savings in assemble time wouldn't really outwight the hassles of working online and saving memory blocks. – Raffzahn Feb 12 '21 at 22:09
  • I did an EE Masters degree starting in 1978 using a MC6802. I had no assembler. I wote in assembly language and hand assembled to machine code calculating relative jumps etc as needed. You get used to it :-) . The project involved acquiring audio call progress signals from a telephone exchange and providing real time control to transferr them via an 128 x 8 multiplexer (CD4051 etc) to 8 x tone decoders. It drove a paper tape punch for logging output (tape was fed to a Burroughs B6700 mainframe for processing). Yes, it's doable :-). – Russell McMahon Feb 13 '21 at 09:43
  • 1
    As far as writing programs on non-existing computers goes, there's also MIX (and friends). – ilkkachu Feb 13 '21 at 18:30
  • 1
    In what sense was MIX non-existent? I've programmed one. It was a microprogrammed implementation; the microcode engine was a KDF9 :-) – dave Feb 13 '21 at 21:20
  • All my early 6502 programs were hand assembled. All my peer group had were the monitor and ROM listings at first. Soon, we had copied down the instruction set from a borrowed databook. – Spud Feb 14 '21 at 06:23
  • 1
    At first, it was small things. Copy block of RAM. Make sound. Multiply. Then bigger things, plot pixel, etc... one made and proved pieces, then combined them. We were high school kids. It is not so hard to imagine Woz doing Integer BASIC this way. He had resources to work from. Many did not have their own machine. Was common to do a program, then type HEX in, BSAVE it, then test, debug, BSAVE again. – Spud Feb 14 '21 at 06:29
  • After a while, one could load in lots of code, then work on whatever small bit was at hand to work on next. My first ones were for an Apple. I got hold of an Atari, had less to work with, only the BASIC, no monitor. Had to write BASIC programs to help with machine language. Mowed a lot of lawns to get an assembler. Others wrote various ones and people shared these programs too. – Spud Feb 14 '21 at 06:34
  • For perspective, the magazines in the grocery store were publishing assembly listings. Hand assembly was not so crazy then. – Spud Feb 14 '21 at 06:35

4 Answers4

74

TL;DR:

As explained on Steven Weyhrich's great and authoritative Apple II History Site, Wozniak simply sat down and wrote his Integer-BASIC (*1) on paper, while assembling it at the same time by hand. In his own words:

I had no assembler, that was another thing. To use an assembler, they figured that somebody was going to buy this processor to use for a company, and their company can pay a few thousand dollars in time-sharing charges to use an assembler that was available in time-share. I didn’t have any money like that, so a friend taught me that you just sort of look at each instruction, you write your instructions on the right side of the page, you write the addresses over on the left side, and you then look up the hex data for each instruction–you could assemble it yourself. So I would just sit there and assemble it myself. The BASIC, which we shipped with the first Apple II’s, was never assembled – ever. There was one handwritten copy, all handwritten, all hand-assembled. So we were in an era that we could not afford tools.

This quote is taken from a transcription of a speech Wozniak held at he Apple World Convention in 1986. See here for the section about his BASIC.


The Question

Was this simply a high-level concept, actual machine code for the 6502, or an actual implementation on a different system?

Actual machine code on paper for the 6502. (*2,*3)

Was the development only on paper, or was a host computer involved (possibly at his work at HP)?

On paper. A computer was used to test the implementation of the stack machine evaluating expressions. It was written in ALGOL. In addition it is mentioned that he used a HP calculator as well to get used to stack-'thinking'

Did he test it elsewhere before putting it on the Apple 1?

Only on the Apple 1 - they didn't had the money to buy computing time for a cross assembler, as he mentions.


How was this possible?

While it's not a job for an extended weekend, writing a BASIC is not as hard as some may think. To start with, a BASIC is at the core a rather simple program consisting of a few fixed parts like

  • A line editor
  • A cruncher (tokenizer) (*4)
  • A fetch and execute loop
  • An expression evaluator
  • Memory (variable) access
  • (Garbage collection *5)
  • An error handling/output function
  • Startup (cold boot) and recovery (warm boot)

Each of them are rather short tasks and can be written down independent. Some just a few lines, some may require a up to a hundred instructions.

The rest of an interpreter is

  • a collection of functions

One for every BASIC command, every Instruction and every function. They are what the fetch and execute loop calls with every found token, which brings the last two parts:

  • A list of all commands, instructions and functions to be searched and pointing to its entry point
  • A list of error codes/messages

All of these parts are on their own quite manageable on paper and by hand. To give some rough numbers (*6), Integer BASIC occupies 6 KIB of code made up from about 2000 instructions (plus a bunch of tables). With over 50 user visible commands and function this would already average to less than 40 instructions per function. In reality most are way shorter, like PEEK or POKE being 4 instructions each. Even complex one like GOSUB and GOTO are only 14 and 26 instructions.

Programming is about organization of your task, BASIC is not only no exemption to this, but a perfect candidate due the way it operates. Or in his own words:

It was a very efficient approach that broke up a large task in a very orderly way.


*1 - The name Wozniak used, at the time and for the Apple 1, was Apple BASIC, but to a wider audience it was only introduced way later and with some extensions for the Apple II, now named Integer-BASIC. By now the term Apple BASIC is more closely associated with Apple's Microsoft dialect Applesoft. Thus the term Integer-BASIC is used thruout the answer, despite being not all exact.

*2 - Since he did it in 6500 assembly, it can be assumed that this happened after acquiring a first 6502 at Wescon in September 1975. What's interesting is that despite having a 6502 and writing a BASIC in 6500 Assembler he still made the board to accept a 6800 as well.

*3 - 6502 Assembler is rather easy to translate by hand, as every mnemonic plus addressing mode equals a single opcode and parameter encoding can as well be directly made according to addressing mode. No complex encoding to manage, like on a 8086 or 6800.

*4 - Optional, but Woz did add it to save on RAM.

*5 - Usually, but Integer BASIC worked without.

*6 - These numbers are taken from Integer BASIC for the Apple II, which is the only one I had a disassembly at hand). The original Apple 1 BASIC is only 4 KiB and had about a dozend functions less, but the basic considerations match.

Raffzahn
  • 222,541
  • 22
  • 631
  • 918
  • 13
    You make it seem simple. Having written a couple of Lisp interpreters myself, in higher level languages, I think the line editor, the expression evaluator and the variable storage are not really "simple tasks". – chthon Feb 12 '21 at 08:38
  • 5
    @chthon Well, LISP's variables model has from the very beginnings been a lot more complex than BASIC's. BASIC had no concept of binding and unbinding, just plain static variables. – Ralf Kleberhoff Feb 12 '21 at 10:41
  • 2
    @chthon An expression evaluator is very simple to write if you know (or figure out for yourself!) the theory of how to do it. Stack-based algorithms (e.g. reverse Polish notation) had been known for 30 years before Woz. – alephzero Feb 12 '21 at 10:47
  • 7
    @chthon Well, it is. A line editor is simply a routine that takes a line (if there is no OS function to collect a line, it's adding each pressed key to the end of a buffer or removing one if BS is pressed, ending with CR - to be reused for INPUT), checks if there's a number in front, if yes it gets saved, the rest of the line is handed to the cruncher, and if no number handed to the fetch loop, otherwise the line number is used to search for a location and the crunched line inserted there. Done. This can be done in 50-100 instructions. Some tasks are less work in assembly than in a HLL :) – Raffzahn Feb 12 '21 at 11:44
  • 3
    Nitpick: You call it Integer BASIC, but that was for the Apple II, not the Apple 1. There is a difference, which is described here. However, both were written by Woz. – DrSheldon Feb 12 '21 at 12:53
  • @DrSheldon True, then again, nowadays People do associate the name Apple BASIC foremost with Applesoft. – Raffzahn Feb 12 '21 at 12:54
  • 19
    I know it sounds implausible today, but I hand-wrote 6502 machine code back in the day, and I'm certainly not that rare. – DJClayworth Feb 12 '21 at 14:16
  • 14
    I feel a surreal mixture of awe, envy and pity. – Peter - Reinstate Monica Feb 12 '21 at 14:20
  • 1
    What I can't find in the article - did he burn it in ROM before ever having tested it, or did he have some way to test it in RAM (possibly using another ROM with a simpler editor to put values into RAM) before committing the BASIC interpreter to ROM? – Erwin Bolwidt Feb 13 '21 at 00:53
  • 2
    @ErwinBolwidt Apple 1 BASIC was not offered in ROM, but but had t be loaded from cassette. – Raffzahn Feb 13 '21 at 01:14
  • @Raffzahn Thanks. That's cool. I found a page about the Apple-1 cassette interface card, in case anyone is interested. – Erwin Bolwidt Feb 13 '21 at 01:44
  • 4
    I did an EE Masters degree starting in 1978 using a MC6802. I had no assembler. I wote in assembly language and hand assembled to machine code calculating relative jumps etc as needed. You get used to it :-) . The project involved acquiring audio call progress signals from a telephone exchange and providing real time control to transferr them via an 128 x 8 multiplexer (CD4051 etc) to 8 x tone decoders. It drove a paper tape punch for logging output (tape was fed to a Burroughs B6700 mainframe for processing). Yes, it's doable :-). – Russell McMahon Feb 13 '21 at 09:43
  • 4
    I can’t claim the same historical aspect as some of the others commenting here, but I’ve gone the hand-assembled route a couple of times before myself with more modern hardware (AVR and MSP430, both on a couple of occasions) simply to help learn about the platforms a bit more. Other than the jump and branch computations, it’s not particularly difficult if you have a proper ISA reference available. Where it gets challenging and into the realm of ‘awe’ is doing it without documentation readily available, which is an increasingly rare skill. – Austin Hemmelgarn Feb 13 '21 at 16:00
  • How was the project worked into machine-readable form and edited? Did Woz start by getting a cassette interface working, or did he have an ASR-33, or what? – supercat Nov 15 '21 at 17:08
  • Well, he had the Apple 1, so he could quite easy key it in, using the 256 Byte WOZMON stored in a PROM (programmed with a promer at HP) and save it using the cassette interface (which works fine without the BASIC). – Raffzahn Nov 15 '21 at 18:13
  • @Raffzahn: Thus my comment about "did Woz start by getting a cassette interface working", though that still leaves open questions about how one would edit a raw machine language program. When developing DOS programs using debug, I would frequently insert some padding to allow for the possibility that code changes might make some routines bigger without having to cause anything else to move, but if a program as hand assembled on paper, it would be possible to also use pencil and paper to maintain a list of patch-ups that would be needed if parts of the code get moved. – supercat Nov 17 '21 at 22:39
  • @Raffzahn: I would think that a combination of a tape punch and a high-speed tape reader that was tolerant of splices could be a powerful combination if one designed a tape format that was designed to facilitate editing of machine-code programs via cutting and splicing, with relocation fixups applied automatically. Somewhat like a very primitive assembler that was limited to DB and DW directives, and required all symbols to be of the form S0001, S0002, etc. I wonder if anyone designed such a system back in the day? – supercat Nov 17 '21 at 23:06
40

One thing is certain: Steve Wozniak was very good at hand assembling 6502. Instead of writing assembler mnemonics he could simply type in the necessary hex code.

I realize this isn't a proper answer but this anecdote is simply too good to relegate to a comment. It comes from Bill Atkinson remarking on Steve doing some assembler work:

The other thing that happened then is I had to plug in the disk routines, and their system was pretty big and that little 13-sector floppy disk didn't have a lot of capacity. Well, Woz had just come up with a different way of encoding the data on the disk so that we could get more data for the same disk size, and we needed the 16-sector disk routines. And so Woz came down, and I was there... I had never bothered to get a motel because I slept on the bench when I wasn't working. This is in the computer science lab at UC San Diego. I was busy, I didn't have time to go sleep.

But Woz came down, and I got to interact with him and it was really fun because he was working on installing these 16-sector disk driver routines, and he'd go 'type type type type type' -- and he didn't type in assembly language and have it assembled. No, he'd type in 6502 machine code. Hex. -- He'd type in hex, and then, you know, watching him type and he'd go 'type type type' -- pause -- 'type type type type', and when he finished I asked him what was the pause? And he said "forward branch, seven instructions, I had to compute the offset before I continued". So, he didn't back-patch the offset, he actually looked at what he was going to be typing, knew how many bytes it would take... he was brilliant.

From an interview: https://youtu.be/6tUWoy1tJkE?t=45m

I've borrowed this wholesale from: https://news.ycombinator.com/item?id=14824949

George Phillips
  • 7,676
  • 36
  • 32
  • 8
    I suppose when you do antyhing enough, you get extremely good at it. – user253751 Feb 12 '21 at 12:10
  • 3
    I got to see Woz speak once a few years ago. The guy is just on a different level from the rest of us. Absolutely brilliant engineer. – Seth R Feb 12 '21 at 16:13
13

Woz was exceptional, but not the only one with this (moderate level of ?) skill in machine language. Lots of teens/kids learned to poke (from Basic) absolute hex machine code into memory on several models of personal computers (not just the Apple I/II). I knew some who could speak out-loud a small subroutine in hex for the 6502, no assembly language or even paper coding form needed.

As for needing a computer to code, also not true. Tons of computer programming was done, not only in the 8-bit era, but in the punch card era on paper coding sheets, and hand assembled. Some programmers needed to debug their (Edsac, Manchester, Bendix, et.al.) code when the first run(s) failed. But a non-zero number of programmers did not, since the turn-around cost was high enough that some just hand checked their code sufficient to not have off-by-one branching errors, etc.

There are lots of lost arts due to modern technologies.

hotpaw2
  • 8,183
  • 1
  • 19
  • 46
  • 2
    And a lot of BASICs didn't even have hex, so many were pretty good at writing these things in decimal – Artelius Feb 13 '21 at 00:23
  • 4
    I think this is the first time I've seen "lost arts due to modern technologies" applied to 70s/80s computer skills, and not, y'know, blacksmithing or firestarting or swordfighting or… – Tim Pederick Feb 13 '21 at 06:24
  • 3
    @DrSheldon The question has already been answered in full by another user; I don't think there's anything wrong with adding on with corrections, information, etc. that readers might find interesting, and that wouldn't fit well in comments. – yeah22 Feb 14 '21 at 06:16
  • 3
    This does not answer the question, which is about what Wozniak did. – DrSheldon Feb 14 '21 at 16:11
1

I would like to note that it was the hand-entered code that ultimately did in Integer BASIC.

Jobs demanded floating point for the II, and although Woz had already written an FP library by that point, it had to be integrated into IB. It was simpler to just use the MS code they had licensed, as it was in assembler and somewhat documented, so porting their graphics code into that was easier than back-porting FP into Integer by hand-entering hex.

Which is sad, because had they done that I have zero doubt that we would have been using string slicing instead of MS's abysmal MID/LEFT/RIGHT. Every other BASIC I can find from that era uses slicing, only the PET used MS at the time, everyone else had their own variety.

Maury Markowitz
  • 19,803
  • 1
  • 47
  • 138
  • Aside from the fact that the garbage collector was designed to be compact rather than efficient, what's wrong with the MS approach? It could have been improved perhaps with a function to compute mid$(a$, s, e-s) without having to repeat s, or to compute mid$(a$, s, 1) without having to evaluate the 1, but for many tasks it seems as or more convenient than the slicing approach used by e.g. HP BASIC. – supercat Nov 15 '21 at 18:10
  • @supercat - slicing does not produce a new string, just a pointer. MS functions create new strings. slicing uses less memory, is much faster, and doesn't eat up RAM. – Maury Markowitz Nov 16 '21 at 14:31
  • Slicing requires that one know in advance the lengths of strings one will be using, or waste memory on oversized reservations. MS actually gets by with a very low memory footprint if the time spent on GC isn't a concern, and spending a little more effort and ROM space for the GC code would have made it possible to enormously improve its efficiency, especially if string literals (and other strings) had been stored prefixed by length or one were willing to waste a byte per allocation (if only strings with length of at least one were kept in memory, the length byte would suffice). – supercat Nov 16 '21 at 15:47
  • How efficiently could string-slicing BASICs hold e.g. a list of 100 strings with an average length of 8 but a maximum length of 32? In MS-BASIC, that would take 1100 bytes, but from what I understand in string-slicing dialects it would take 3200. – supercat Nov 16 '21 at 16:01
  • Atari BASIC parses everything at edit time, not runtime. As part of this process, it removes quotes from string constants and places a two-byte length token at the front. So the space is exactly that of the original constants, or in this case, 800 bytes. Perhaps I do not understand what you are asking. – Maury Markowitz Nov 17 '21 at 12:41
  • Could any string-slicing-based BASICs accommodate arrays of strings? In MS-BASIC, if one says dim a$(3):a$(0)="supercalifragilisticexpialidocious":a$(1)="wow"+str$(ti):a$(2)="ok", one could then output any of those with print a$(index). Could one do such a thing in string-slicing dialects without having to reserve an object with space for 3x34 characters? – supercat Nov 17 '21 at 17:34
  • HP did, they used [ and ] as alternatives that allowed A$(1,5)[1,4]. Not sure why no one copied that. It does lead to some confusion porting from HP as well, but that's not much of an issue these days... – Maury Markowitz Nov 18 '21 at 14:02
  • Would that accessing characters 1 to 4 of element (1,5) of array A$? Could such an array reserve different numbers of characters for different elements? – supercat Nov 18 '21 at 15:25