Sunday, September 2, 2012

Apple-1 Hello World Tutorial

I feel like I've been deciphering ancient Dead Sea scrolls. Or if not exactly that, at least I've been dusting the dusty tomes of home computing. I printed the Apple-1 Operation Manual couple of days ago and started to figure out how to do some Hello World with the legendary device.

Apple-1. Image by Kyro
As you may know Apple-1 is the original garage produced computer from the newborn Apple Computer Company sold in 1976.  Nowadays it's a collectors item, because only about 50 of them is known to exist. Luckily there are excellent emulators available.

As I'm walking down history lane I get little bit carried away and I try to get a glimpse of the original home computing experience from 35 years back. I try to manage with the documents of the time, which are the already mentioned Operation Manual and MOS 6500 processor data sheet.

While reading the manual, the nature of the machine and the way it was meant to be used becomes clear. It can only display text, no graphics. Operating System (the manual calls it System Monitor) is hard coded in the device and it provides functions to user for manipulating and viewing memory contents and for starting programs in the memory that user has somehow managed to enter there. The whole OS is only 256 bytes long and it's machine code is fully printed and commented in the Operation Manual taking only two pages.

The machine is expandable, you can attach some kind of tape drive to save and load programs. There also might have been some assembler programs to ease programming a little bit, but not sure if they existed back then. At least not much free memory would have been left for actual work if assembler was also loaded in the memory.

Because the machine is so limited I doubt not many hobbyists really spent much time running the programs, but instead the entertainment was about programming in machine code by entering values directly into memory. No compilers needed, simple.

Lets do that. When you switch the computer on it greets you with the prompt and is ready to take your input:



Now the Operation Manual comes in handy because it tells how the memory manipulation and inspection is done. It also tells that addressable memory locations are 0000-FFFF, although there is not that much memory in the machine. Actually most of the address space is unused and not available. The manual also tells that the OS (all the 256 bytes of it) is visible in the address space FF00-FFFF. Let's confirm and see the first 48 bytes of it by entering command "FF00.FF2F":


Seems to match with the Operation Manual:


That manual printout also tells how you're supposed to orient your thinking when programming machine code for the MOS 6500 series processor. Each command consists of 1-3 bytes where the first byte is the command itself and rest, if any, are it's attributes such as memory locations and plain numeric values the command is going to use. These commands are actually called op-codes. In the listing above op-codes used are D8, 58, A0, 8C, A9 and so on.

Now comes handy the MOS 6500 processor data sheet as that is the place to check what each op-code actually means and what is available. There you can also learn that op-codes are further grouped so that op-codes doing similar thing in little bit different way form groups which are called mnemonics. One of those mnemonics is LDA (comes from LoaD A, I think) and it's used for putting some value into processor's A register.


From the screenshot you can see LDA comes in 8 varieties represented by op-codes A9, AD, A5, A1, B1, B5, BD and B9. These different varieties are called addressing modes and basically the difference between each mode is that the addressing mode defines what next 1-2 bytes after the op-code byte mean. For example LDA when used with op-code A9 it means value of the next byte after op-code is copied to A register. If using LDA with op-code AD, it means value to the A register is copied from the address defined by next 2 bytes after the op-code. Two bytes are needed to define an address in the address space of 0000-FFFF. Rest of the LDA op-codes work in similar way, but they may for example combine value from other two registers (X or Y) when formulating the address from where the value is copied to A register or do some other trickery of sort.

There is over 50 mnemonics and with them you can naturally do what every computer program does: read and write memory locations, do arithmetics, loops, compare values to branch code execution path etc.

All this in mind and with little bit of trial and error I was able to do my Hello World program. It's 40 bytes long in the memory location 1000.1027:


Here the program has also been successfully run with command "1000 R" producing the heart warming output.

And here is the code with comments:


1000: A2 0                       LDX 0, load 0 to X register
1002: BD 13 10                   LDA X+1013, load value from address 1013+X to A register
1005: 20 EF FF                   ECHO A, call apple1 OS function in FFEF to echo char in A
1008: E8                         INX, increment the value in X register by 1
1009: E0 15                      CPX 15, is X value 15? (length of text output)
100B: F0 3                       BEQ, if it is, jump 3 bytes forward to address 1010
100D: 4C 2 10                    JMP to 1002, loop back to print next character
1010: 4C 1F FF                   JMP to FF1F, out of the program to OS area
1013: 8D 8D 8D 48 45             CR CR CR "HE"     data to output
1018: 4C 4C 4F 20 57 4F 52 4C    "LLO WORL"        data to output
1020: 44 20 21 21 21 8D 8D 8D    "D !!!" CR CR CR  data to output


I'm not sure if my way of exiting the program is a the preferred way, I just jump to OS area to a location that seems to work well. Meaning that the machine doesn't hang and it starts to accept user input again.

Other thing worth mentioning is a call of an OS function in the address program address 1005. That is a sub routine call to OS location FFEF where located is a function that prints to screen the ascii character of the value that's in the processor's A register.

Fascinating stuff.

1 comment:

  1. Fascinating indeed, such a beautiful machine… I'm scratching the Apple I system programming and your page where invaluable, thank you Sampo!

    ReplyDelete