Suite8080 0.4.0
I released version 0.4.0 of Suite8080, the suite of Intel 8080 Assembly cross-development tools I’m writing in Python. It bundles some minor features and changes I did while thinking about what major task to work on next.
New features
There are two main new features in this release.
The first is the ability of asm80 to save the assembled program’s symbol table in the .sym CP/M file format. The other feature enhances the assembler to accept the double-quote character ” as a string delimiter, which means strings and character constants may be written as ”This is a string” and ”F”.
In addition, the output of the assembler's help message (-h option) and verbose mode (-v) is now slightly more descriptive and complete.
Saving the symbol table in .sym format
The Digital Research assembler that came with CP/M, the most popular operating system for 8080 microcomputers in the 1970s and early 1980s, could save symbol tables to .sym files, which map the labels of Assembly programs to their memory addresses.
Why did I add .sym support to the Suite8080 asm80 assembler?
Because the Digital Research symbolic debugger, SID, lets me load symbol tables and refer to program labels by name instead of raw memory addresses. For example, from SID I can load a program, run it from an instruction pointed to by a label, set a breakpoint at a label, and so on.
Implementing .sym support
Section 1.1 "SID Startup" on page 4 of the SID Users Guide, the Digital Research symbolic debugger, describes this simple text file format. A .sym file contains entries comprising a hexadecimal 4-digit address and the corresponding symbol name truncated to 16 characters, separated by a space. Although a line can hold more entries separated by tabs, for simplicity the files asm80 saves have only one per line.
What does a symbol table file look like? This is the greet.sym file of the greet.asm hello world CP/M Assembly demo of Suite8080:
0005 BDOS
0009 WSTRF
0109 MESSAGE
All I did to implement .sym support was adding the single function write_symbol_table() to the assembler. Here’s the code:
def write_symbol_table(table, filename):
symbol_count = len(table)
if symbol_count == 0:
return symbol_count
with open(filename, 'w', encoding='utf-8') as file:
for symbol in table:
print(f'{table[symbol]:04X} {symbol[:16].upper()}', file=file)
return symbol_count
symbol_table is a global dictionary holding the symbol table.
The only specification of the file format I found makes no mention of symbol case. But the Digital Research assembler uppercases symbols, so asm80 does too.
Although the Digital Research assembler sorts the entries of .sym files alphabetically by symbol name, asm80 diverges from this practice and leaves them unsorted. Again, the SID manual doesn’t mention sorting and some examples it presents are unsorted. SID accepts unsorted files.
To complete the implementation, I added to function main() the code to process the -s command line option for saving the symbol table. With the new option, and the way it combines with other options, the logic to process them grew a bit in main(). Perhaps the argument processing code is ripe for breaking out of main() into its own function.
Documentation and demos
Suite8080 0.4.0 includes a new document describing the usage of the Suite8080 tools and expands the design notes by covering the assembler’s parser. Some minor updates to the README.md file list only the currently available Suite8080 tools and add links to the source tree directories it references.
I changed the memcpy.asm and upcase.asm Assembly demos to make them run on CP/M. These programs produce no visible output. Therefore, to inspect how they alter the machine state, you need to run them inside a debugger such as SID or DDT.
Bug fixes and other changes
The work on the 0.4.0 release involved also some refactoring of asm80 to remove redundant declarations of global variables, break the code that saves the assembled program out of main() into its own function, and tweak the code that processes the default output file name.
Finally, I fixed a bug that made the assembler ignore the -o option when building the output file name and - was supplied as the input file.