APPENDIX B: SETTING UP LINUX FOR ALTAIR 8800¶
Written by Kevin Cole (ubuntourist@hacdc.org) 2020.10.18
These instructions will provide users with the ability to use their own Linux computer to:
write programs for the Altair using meaningful mnemonics (abbreviations) for the machine instructions instead of toggling binary numbers into switches,
assemble those programs from source code file (the meaningful mnemonics) into executable object code file, which consists of the binary numbers that would have been toggled in,
produce a list file which is a report showing both the source code and the corresponding binary machine code, as well as a list of errors, and other useful information regarding the assembly of the source code,
test the code in an Altair software simulator running on their computer,
establish communications between their Linux computer and the Altair,
send executable object code files to the Altair,
and, send data from their Linux computer to the Altair and receive data back.
Beginners should start with a computer running the Raspberry Pi Desktop operating system.
PACKAGES¶
First, start by install the Macroassembler AS. Go to the download page and download the latest beta version of the C Sources Click the as bz2 link at the end of the first line in the list.
To build and install, your system will also need LaTeX
, which is part of
the texlive
package.
Note
The steps below assume you are running on a Linux system that has all of the programs needed to build the application and its documentation. If you are running the Raspberry Pi Desktop operating system, everything is fine. You can proceed without worry.
The
make docs
step below will complain 10 or 11 times that it is missing the filegerman.sty
. Unless you need the documentation in German, you can safely ignore the error. Just pressENTER
each time it complains.make install
(as of 2021.09.13) has introduced an error saying it cannot create directory‘/usr/local/include/asl/.’
because it already exists, but the error can safely be ignored. (I have submitted a fix which may be accepted by the time you read this.)If you are NOT on a system running the Raspberry Pi Desktop, see the
INSTALL
document for more gory, hoary details regarding other systems and customization.The last step below removes the broken German documentation.
Type the following:
$ sudo apt update
$ sudo apt install texlive texlive-latex-extra
$ cd ~/Downloads
$ wget http://john.ccac.rwth-aachen.de:8000/ftp/as/source/c_version/asl-current.tar.bz2
$ tar xjvf asl-current.tar.bz2
$ cd asl-current
$ cp -v Makefile.def-samples/Makefile.def-unknown-linux Makefile.def
$ make
$ make test
$ make docs
$ sudo make install
$ sudo rm /usr/local/doc/asl/as_DE.*
Next, obtain:
an old-school communications program (
minicom
),a file transfer protocol add-on (
gkermit
) forminicom
,a software Altair simulator (
simh
) andeveryone’s favorite pager (
most
). See below: It comes in handy.
You can probably skip gkermit
but it “rounds out” minicom
which, by default wants to have a version of Kermit “at the ready”,
even if the Altair won’t use it. Install them all with:
$ sudo apt update
$ sudo apt install minicom gkermit simh most
WRITE AND ASSEMBLE SOURCE CODE¶
Then using your favorite editor – even if it isn’t emacs
–
create an assembler source file, program.asm
for example. To
understand the syntax of the source file, study:
the Intel 8080 Programming Manual (PDF)
- the Macroassembler AS documentation, available as:
HTML (/usr/local/doc/asl/as_EN.html) and
plain-text (/usr/local/doc/asl/as_EN.doc)
the Intel 8080 Microcomputer Systems Users Manual available, along with several other goodies, from the Bitsavers archive
For example, the source code below is an assembler language version of the addition program from Part 3, Section B of this manual that was toggled into the front panel.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; NAME: add.asm
; AUTHOR: Kevin Cole ("The Ubuntourist") <kevin.cole@novawebdevelopment.org>
; LASTMOD: 2020.10.06 (kjc)
;
; DESCRIPTION:
;
; This is the assembly source code that produces the same machine
; op codes as shown by the first example (add two numbers) in the
; Altair 8800 Operator's Manual.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Code segment:
ORG 0o ; Set Program Counter to address 0
START: LDA VAL1 ; Load value (5) at VAL1 (200) into Accumulator
MOV B,A ; Move value in Accumulator to Register B
LDA VAL2 ; Load value (8) at VAL2 (201) into Accumulator
ADD B ; Add value in Register B to value in Accumulator
STA SUM ; Store accumulator at SUM (202)
JMP START ; Jump to start of code (infinite loop)
; Data segment:
ORG 200o ; Set Program Counter to address 200
VAL1: DB 5o ; Data Byte at address 200 = 5
VAL2: DB 10o ; Data Byte at address 201 = 8 (10 octal)
SUM: DB 0o ; Data Byte at address 202 = 0
END ; End
Assemble it with:
$ asl -a -cpu 8080 -L -listradix 8 program.asm
which produces a list report (program.lst
) and an object file
(program.p
) Compare the generated list file to the octal machine op
codes provided in the manual.
However, if you have installed most
– you know you want it – it is
VERY instructive to instead assemble the source file with the
command:
$ asl -a -cpu 8080 -L -listradix 16 program.asm
This produces the same binary file (program.p
) as in the first
command but changes the format of the list file, displaying the
machine op codes in hexadecimal, rather than octal, and, together with
the command:
$ most program.p
you can study the actual binary “executable” produced, and “debug” it
by finding the machine op codes (in hex) embedded in the executable
(by comparing it to program.lst
).
Whichever way you assemble, you’ll want to produce a program.bin
and
program.hex
file by issuing:
$ p2hex program.p
$ p2bin program.p
(Look at both the .bin
and .hex
files with most
and
compare that with what you see in the .p
and hexadecimal list
file.)
RUN YOUR PROGRAM IN THE SOFTWARE SIMULATOR¶
The simh
Debian package simulates at least 30 different
architectures – including seven others besides the Altair that I had
the pleasure of spending time with.
Each simulator is started with a separate program. The Altair
simulator is named, logically enough, altair
. In order to use it:
Start the siimulator (
altair
).As on the front panel of the actual machine, reset (
reset all
).Load your binary file into the simulator’s “memory” (
load program.bin
).Start the program running (
run
).If the program does not finish and stop on its own, you need to stop the simulation by pressing
Ctrl-E
(which will display as^E
).Examine memory locations with
e
followed by the address, or read up and experiment with other simulator commands shown by thehelp
command.When finished, type
exit
.
Using the addition program above as an example, enter the following:
$ altair
Altair 8800 simulator V3.8-1
sim> reset all
sim> load program.bin
131 Bytes loaded.
sim> run
^E
Simulation stopped, PC: 000004 (LDA 201)
sim> e 202
202: 015
sim> e PC,A,BC,DE,HL,C,Z,AC,P,S,SR,WRU
PC: 000004
...
sim> exit
Goodbye
$
The second examine
(e
) command above lists the registers and
other useful locations.
Mnemonic |
Meaning |
---|---|
PC |
Program Counter |
A |
Accumulator |
BC |
Register Pair BC |
DE |
Register Pair DE |
HL |
Register Pair HL |
C |
Carry flag |
Z |
Zero flag |
AC |
Auxillary Carry flag |
P |
Parity flag |
S |
Sign flag |
SR |
Front Panel switches |
BREAK |
Breakpoint address |
WRU |
Interrupt character |
There are LOTS of other commands to the simulator, but the above gets
the basic job done. Ctrl-E
stops the program currently running in
the simulator, and reports the current program counter (PC) and the
instruction being executed when stopped.
If you were running the program shown above, the list file tells
us that data byte (DB) labeled SUM is at memory address 202
(octal). Using the simulator’s e
command to examine that address
reveals that it contains the data value 015 (octal).
Note
You should remember that the program above (the add two numbers program from Part 3, Section B) is an infinite loop and is repeating the code over and over again very quickly.
When you stop the simulation by pressing Ctrl-E
there is no way
to know which instruction was being executed at the time. This
means that the Program Counter PC and the instruction it is
pointing to will vary with every running of the simulation – unless
you are a supercomputer yourself and have incredibly quick reflexes.
In my example above, you can see that the Program Counter was at
000004 and executing the instruction LDA 201
when the
simulation was stopped, but it will likely be different for you.
The 131 Bytes loaded.
above is in decimal. Counting in octal,
that would be 203 bytes. You will note that the program starts at
memory address 000 (octal), and that the sum of the addition, which
is the last byte of memory that the program uses, is at memory
address 202 (octal). In other words, the program is contained in
the first 203 (octal) bytes of memory – though bytes between byte
015 (octal) in memory, which is the last byte of actual instruction
code, and byte 200 (octal) where the first value to be added is
stored, are unused, and therefore those bytes are uninitialized,
and will contain unpredictable random values.
A summary of the more useful simulator commands provided by the help
command:
r{eset} {ALL|<device>} |
reset simulator |
e{xamine} <list> |
examine memory or registers |
ie{xamine} <list> |
interactive examine memory or registers |
d{eposit} <list> <val> |
deposit in memory or registers |
id{eposit} <list> |
interactive deposit in memory or registers |
ev{aluate} <expr> |
evaluate symbolic expression |
ru{n} {new PC} |
reset and start simulation |
go {new PC} |
start simulation |
s{tep} {n} |
simulate n instructions |
Note
The simh
Debian package is hopelessly out of date, and if your
programs become complex enough – for example, trying to load the
entire CP/M operating system into the simulator – it will
barf. Newer versions are available from both the Altair clone
site and the GitHub repository.
CONNECTING THE ALTAIR CLONE¶
After unboxing, plugging in and powering up, the status is:
inte
prot
MEMR
inp
M1
out
hlta
stack
WO
int
WAIT
hlda
where the upper-case, bold represents the LEDs that are “ON” and the lower-case represents the LEDs that are “OFF”.
Plug the serial cable into both the TOP port on the back of
the Altair and any USB port on the Linux box. Then issue the command lsusb
.
A new USB device should appear in the list:
Bus 003 Device 002: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
In addition, after plugging the cable in, you should see two new entries in the
/dev
directory: a /dev/ttyUSB0
device and a /dev/serial/
directory.
It’s that /dev/ttyUSB0
we’re looking for.
CONFIGURING MINICOM¶
First, verify that your system identifies the cable as
/dev/ttyUSB0
. (This can vary from computer to computer,
particularly depending upon what you have plugged in at the time.)
The only way I know of to do this is, both before and after plugging
in the cable, issue the command:
$ ls /dev/tty*
and check for the differences between the two. There should be a new
/dev/ttyUSB0
or /dev/ttyUSB1
– or possibly another number,
depending upon the number of other USB devices plugged in and
identifying themselves as a terminals. [I have also seen systems that
use /dev/ttyACM0
(or 1
, or 2
, etc.) to identify USB
devices capable of communicating like a terminal.]
Note
If you intend to connect the Altair 8800 clone to the same computer
frequently, it may be worth setting up a udev
rule. Create a
file named 99-local.rules in /etc/udev/rules.d/
as follows:
$ sudo cat > /etc/udev/rules.d/99-local.rules <<EOF
# Written by Kevin Cole <ubuntourist@hacdc.org> 2020.10.19 (kjc)
# Custom udev rules
#
# Create a symlink ALTAIR for Prolific Technology USB-Serial Controller
# (idVendor=067b, idProduct=2303, driver=pl2303)
#
# Determined via:
#
# $ udevadm info -a -n /dev/ttyUSB0 | grep -i "driver"
#
SUBSYSTEMS=="usb", \
DRIVERS=="pl2303", \
SYMLINK+="ALTAIR"
EOF
$ sudo udevadm control --reload-rules && sudo udevadm trigger
The serial
attribute can be determined via:
$ udevadm info -a -n /dev/ttyUSB0 | grep "[\{]serial[\}]"
and ATTRS{serial}=="..."
used in place of DRIVERS--"pl2303"
but, since the serial attribute changes each time it is put in a
new USB slot, using the drive identification is, I hope more
practical.
minicom
has a perverse sense of humor when it comes to writing its
configuration files in a sane way. So one has to do some stupid
dancing to get it to put a configuration file where you want it. You
can fight with it, or just edit mine to suit your needs. (See the
~/.minirc.altair section below. To fight with it:
$ sudo usermod -aG dialout kjcole
$ cp /usr/share/doc/minicom/examples/minirc.dfl ~/.minirc.altair
$ sudo minicom --setup altair
Filenames and paths
A - Download directory: ~/Downloads
B - Upload directory: ~/Code/Altair
C - Script directory:
D - Script program: runscript
E - Kermit program: gkermit
F - Logging options:
A - File name (empty=disable) : minicom.log
B - Log connects and hangups : Yes
C - Log file transfers : Yes
File transfer protocols:
G kermit /usr/bin/gkermit -i -s
H kermit /usr/bin/gkermit -i -r
Serial port setup
A - Serial Device : /dev/ttyUSB0
B - Lockfile Location : /var/lock
C - Callin Program :
D - Callout Program :
E - BPS/Parity/Bits : 115200 8N1
F - Hardware Flow Control : Yes
G - Software Flow Control : No
Save setup as altair
Exit from Minicom
$ cp /etc/minicom/minirc.altair ~/.minirc.altair
$ sudo rm /etc/minicom/minirc.altair
Note
If you’ve successfully created the udev
rule, you should use
/dev/ALTAIR
as the serial device above, as it will be more
reliable across reboots.
At this point, one should be able to edit ~/.minirc.altair
directly,
though there’s not any documentation on the file format.
~/.MINIRC.ALTAIR¶
Edit your updir
and downdir
to suit. (You probably don’t want
to try putting it in MY home directory.)
# Minicom Altair 8800 Clone configuration
# Last edited by Kevin Cole <ubuntourist@hacdc.org> 2020.10.18
pu pprog7 /usr/bin/gkermit -i -s
pu pprog8 /usr/bin/gkermit -i -r
pu port /dev/ALTAIR
pu baudrate 9600
pu kermit gkermit
pu updir /home/kjcole/Code/Altair/
pu downdir /home/kjcole/Downloads/
GOING “LIVE”: RUNNING YOUR PROGRAM ON THE ALTAIR CLONE¶
Once you have the above in your home directory, you are now ready to load code into the Altair:
$ minicom altair
Welcome to minicom 2.7.1
OPTIONS: I18n
Compiled on Dec 23 2019, 02:06:26.
Port /dev/ALTAIR, 08:32:24
Press CTRL-A Z for help on special keys
Now, on the Altair front panel, raise and hold the STOP
switch, and
while holding, raise and release the left AUX
switch, and finally,
release the STOP
. You should see, in the minicom
window:
=== Configuration Monitor 1.94 ===
1) Floppies
2) PROMs
3) Serial Ports
4) Load .BIN
5) Load .HEX
6) Admin
x) Exit to Altair
Choice:
I have found it slightly easier to load the .hex
files. Loading
.bin
files requires the extra step of telling the Altair what
address to start loading the file at. (The .hex
file has this
information embedded into it.)
Choice: 5
Send .hex file now...
Ctrl-A S
Ctrl-A
, followed by S
brings up the Send file
dialog.
Choose
ascii
as the file transfer protocolG
([Goto]
) followed by the full directory path from your homedirectory to navigate to the
.hex
file. For example, ifprogram.hex
lives in/home/kjcole/Code/Altair/Assembler
, useCode/Altair/Assembler
(This step becomes unnecessary if you configured your upload directory to point to a directory where you keep all your Altair files.)
Type
S
(for[Show]
) to narrow the filename pattern or scroll to the appropriate file and pressSPACE
which should highlight it, and then, eitherO
orENTER
(for[Okay]
, which should already be highlighted.)
You should see something like:
+------------[ascii upload - Press CTRL-C to quit]------------+
|ASCII upload of "program.hex" |
| |
|0.2 Kbytes transferred at 194 CPS... Done. |
| |
| READY: press any key to continue... |
| |
| |
+-------------------------------------------------------------+
Press
ENTER
(or, as it says, any key) and thenx
to Exit to Altair Like so:... 0219h bytes loaded at 0000h === Configuration Monitor 1.94 === 1) Floppies 2) PROMs 3) Serial Ports 4) Load .BIN 5) Load .HEX 6) Admin x) Exit to Altair Choice: x Control Returned to Altair
Finally, assuming you loaded the program at 000, press the RUN
switch
on the Altair clone and you should be “off to the races”.
To exit minicom
and return to the Bash
shell, type Ctrl-A
followed by Q
.
MAKEFILE¶
A Makefile will automate the production of the two list reports, object file, BIN file and HEX file, and even let you assemble several source files at once. The following Makefile accepts the commands:
|
Assemble all |
|
Assemble |
|
Remove all generated files for all |
IMPORTANT: make
likes TAB not SPACE. Change all occurances
of eight consecutive spaces to tabs in the code below!
#!/usr/bin/make -f
# Written by Kevin Cole <ubuntourist@hacdc.org> 2020.10.17 (kjc)
#
# This takes Altair-8800 assembler source files and produces:
#
# - an object file (.p)
# - an Intel HEX file (.hex)
# - a binary executable (.bin)
# - a list report file with octal op codes (.oct.lst)
# - a list report file with hexadecimal op codes (.oct.lst)
# - an include(?) file -- thus far, empty (.inc)
#
# To use:
#
# make # to generate for all .asm files
# or make root # (where "root" is the root of a specific "root.asm")
# or make clean # to remove all generated files
#
############################################################################
SHELL = /bin/bash
OBJECTS := $(patsubst %.asm,%,$(wildcard *.asm))
.PHONY : all
all : $(OBJECTS)
.PHONY : clean
clean :
-rm -f *.hex \
*.bin \
*.lst \
*.inc \
*.p
% : %.asm
asl -a -cpu 8080 -L -listradix 8 $<
mv $@.lst $@.oct.lst
asl -a -cpu 8080 -L -listradix 16 $<
mv $@.lst $@.hex.lst
p2hex $@.p
p2bin $@.p
GETTING INPUT / DISPLAYING OUTPUT¶
If you’re going blind trying to read the blinky lights and make sense out of them, and would just rather see text (and/or if you’d like to be able to type strings of input rather than toggle strings, eight bits at a time), you will need to dig deeper into the mechanics of the 88-2SIO Serial I/O hardware, which is not covered in any of the manuals you’ve encountered so far.
REQUIRED SKIMMING: Altair 2SIO Serial I/O manual (PDF)
OPTIONAL READING: RS-232 Data Control Signals and UART
In order to understand communications between the Altair and an external device like a terminal, connected via the serial / USB cable, the above documents should be perused pondered. They provide details like:
UART |
Universal Asynchronous Recever / Transmitter |
XMIT |
Transmit (OUT) |
RECV |
Receive (IN) |
RTS |
Request to Send |
And settings for synchronous (polled) communication:
15H = 0 0 0 1 0 1 0 1
▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
│ │ │ │ │ │ │ │
│ │ │ │ │ │ └─┴─► 1 = Clock Divide = 16
│ │ │ └─┴─┴─────► 5 = 8 Data bits, No parity, 1 Stop bit (8N1)
│ └─┴───────────► 0 = RTS = Low, XMIT interrupt = disabled
└───────────────► 0 = RECV interrupt = disabled
TIPS¶
Starting with Chapter 6: Utility Programs in the Macroassembler AS manual (page 251).
Working from the object file produced from add.asm
…
plist
plist
summarizes .p
file data:
$ plist add.p
PLIST/C V1.42 Beta [Bld 174]
(C) 1992,2020 Alfred Arnold
Code-Type Segment Start-Address Length (Bytes) End-Address
----------------------------------------------------------------
8080/8085 CODE 00000000 000E 0000000D
8080/8085 CODE 00000080 0003 00000082
creator : AS 1.42 Beta [Bld 174]/x86_64-unknown-linux
altogether 17 bytes CODE
plist
was able to analyze the object file and determine:
the object code contained machine op codes for an Intel 8080 or Intel 8085.
a code block of 14 bytes supposed to be loaded into memory locations 000 to 00D (hex), a.k.a. 000 to 015 (octal)
a code block of 3 bytes should be loaded into 080 to 082 (hex), a.k.a. 200 to 202 (octal)
p2bin
p2bin
converts a .p
file to a binary memory dump, without formatting.
By default, uninitialized bytes become FF
. Although it could potentially
take a very long time to load, this, on the surface, appears to be the most
straight-forward representation of what the memory of the Altair will look
like, once a program is loaded.
p2hex
p2hex
converts a .p
object file to an ASCII representation of
the file (.hex
). There are several different format available for
the output file, based in part on the target machine. In our
example:
$ p2hex add.p
$ most add.hex
:0E0000003A8000473A810080328200C300003F
:0300800005080070
:00000001FF
Looking at the above, and comparing it to the hexadecimal list file produced by the assembler, we can determine that the first two lines represent the two data segments:
Columns |
Interpretation |
|
---|---|---|
Start |
End |
|
1 |
1 |
Colon. Start of record delimiter |
2 |
3 |
Lenghth of data in record |
4 |
7 |
Starting address in memory for data |
8 |
9 |
???? possibly a record type? (00 or 01) |
10 |
N-2 |
Data |
N-1 |
N |
???? possibly a record checksum? |
The first two lines contain 00 in columns 8-9, while the last, which does not appear to have any relation to the machine code shown in the list file, contains 01. Perhaps an “End of Data” record?
Lo and behold, Wikipedia (naturally) has an entry on Intel HEX which confirms, yea verily,
8-9 is a record type indicator, with
00
being data and01
being end of filethe last two characters are a checksum
The entry even offers an example of the checksum calculation algorithm.
KERMIT NOTES¶
In minicom
, the common default kermit
options for both send
and receive were -i -l %l -b %b
which according to C-KERMIT 9.0
Unix man page and tutorial mean:
|
Force binary (Image) mode for file transfer;
implies |
Equivalent to |
|
|
Make a connection on the given serial communications device. |
Equivalent to the |
|
Argument: Serial device name, e.g. |
|
|
Speed for serial device |
Equivalent to |
|
Argument: Numeric Bits per second for serial connections |
gkermit
does not appear to be a full-fledged Kermit as we once
knew it, but, rather the transfer protocol portion only, and depends
on an established communication channel to determine the -l
and
-b
above. So, I’ve removed those two options from my
~/.minirc.altair configuration.
Note
Columbia U. is no longer the home of Kermit. It is now The Kermit Project.