A symbol table says which memory, and where the name was written

The dump was an address and a name. Both of the questions it gets asked
were only half answered.

"What is at this address" was ambiguous, because Program and Data are
separate memories and an address alone does not say which one. That is
easy to miss in a loadable program, where the segments are usually based
far apart - and immediate in a boot image, where both start at zero:
replCalculator has a Program 0003 and a Data 0003 and the old file
printed both as "0003 <name>".

"Where is this defined" was not answered at all, and it is the one that
matters more as a program grows. A name defined once and called in forty
places is hard to find by searching. Lander's table names five files
besides its own; CosmOS and its libraries define over a thousand names
across a dozen.

So: memory, address, name, file, line, separated by tabs, sorted by
memory and then address with Program first. Tabs because that makes it a
table cut, awk and sort already read, and no heading line because
nothing should have to know to skip one. Everything needed was already
being passed to addLabel and thrown away; the file name points at the
copy the include list owns, which outlives the label table.

The manual describes the five fields, and docs.sh now settles that
description against a real dump - the shape, not the values, so that an
example cannot go stale and turn editing a program into editing a
manual. Verified with break.sh three ways: a reordered field, a dropped
field, and a field renamed in the manual.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-09-05 10:21:06 -04:00
co-authored by Claude Opus 5
parent 7a55cfe151
commit 3527812c41
4 changed files with 139 additions and 14 deletions
+22 -2
View File
@@ -420,12 +420,32 @@ Assembler [options] <sourcefile>
| -o, --output \<file\> | Write the output to this path. Without it, the output is named after the source file, in the directory the assembler was run from, taking .bin if it is a boot image and .sbx if it is a loadable program. |
| -I, --include \<dir\> | Look in this directory for included files. May be given more than once, and the directories are searched in the order given. |
| -M, --depend \<file\> | Write out which source files went into the output, as a make rule. |
| -S, --symbols \<file\> | Write every label and the address it was given, in address order, to this path. |
| -S, --symbols \<file\> | Write a symbol table to this path: every label, with the memory and address it was given and the file and line it was written on. |
| -h, --help | Print the options and stop. |
Every option above that takes a \<file\> names a file the assembler WRITES, and the source is the bare argument at the end. So `Assembler -S program.asm` does not dump the symbols of program.asm. It asks for the symbol file to be called program.asm, and then finds it has no source left to assemble.
-S is for looking at what the assembler decided. Every label in the program, in address order, with the address it ended up at: which segment a name landed in, how far apart two routines really are, and whether the label you are looking for was assembled at all.
-S is for looking at what the assembler decided, and for finding your way around a program that has grown past holding in your head. It writes one line for every label, with five fields separated by tabs:
| Field | Meaning |
| -- | -- |
| Memory | Program or Data. |
| Address | Four hexadecimal digits: the address the label was given. |
| Name | The label itself, without its colon. |
| File | The source file the label was written in, named the way the assembler was given it. |
| Line | Which line of that file, counting from one. |
```
Program 5000 start game.asm 31
Program 670D int16add Libraries/math.asm 5
Data 3000 Score game.asm 118
```
Tabs rather than aligned columns, so that the file is a table every ordinary tool already reads without being taught anything, and no heading line, so that nothing has to know to skip one. The file field is what makes it worth having on a big program: a name defined once and called in forty places is hard to find by searching, and this says where it was written.
The memory comes first because Program and Data are separate memories on this machine, so an address on its own does not say where something is. In a loadable program the two segments are usually based far enough apart that the difference is easy to overlook. In a boot image both start at 0x0000, and every address in the table appears twice.
The table is sorted by memory and then by address, with Program first.
The assembler stops at the first error, says which file and line it was in, and exits without writing anything.