Vectors in the symbol table, with both of the numbers they have
A vector is the one thing about a program that nothing else can tell
you. A pinned vector has its number in the source that pinned it, but a
vector the assembler numbered has that number nowhere at all - not in
the source, not in the binary in any form a reader can find. Until now
there was no way to learn that a vector became number 64.
It also cost two hops to follow by hand. The name in "SWI osPrintString"
is not the name of the routine that implements it, so finding the code
meant searching for the vector, reading the handler's name off the
Vector Segment, and searching again. A vector row now names the handler
and gives the line the two were tied together on.
Both numbers, at the user's asking, because neither can be worked out
from the other without knowing which table the vector is in: the Number
is what a program writes and the machine dispatches on, the Address is
where the handler's address is stored, base plus twice the number. The
slot is computed with the same expression the loader is given, so what
the table says and what gets written there cannot drift apart. A vector
a program only declares is listed too - that is how a program says which
vectors it calls, and how two programs can be checked against each other
for agreeing about a number.
A device has no name of its own, being named by the port it is plugged
into, so it is listed under its handler.
The first field is now Kind rather than Memory, because Vector and
Device are not memories. Sorted Program, Data, Vector, Device.
docs.sh checks the six fields against the manual and against real dumps
of two programs - Keys, a loadable program with all four kinds, and
cosmos, a boot image whose segments both start at zero. It now also
checks that a row's name really appears on the line the row names, which
is what catches the string-newline bug fixed in ca6c8ca coming back.
Verified with break.sh four ways: wrong slot arithmetic, vectors
dropped, a field renamed in the manual, and that bug reintroduced.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
ca6c8ca6ad
commit
f3d8985bc4
@@ -420,32 +420,48 @@ 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 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. |
|
||||
| -S, --symbols \<file\> | Write a symbol table to this path: every label and every vector, with where it lives and where it was written. |
|
||||
| -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, 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:
|
||||
-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 and every vector, with six 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. |
|
||||
| Kind | Program, Data, Vector or Device. |
|
||||
| Address | Four hexadecimal digits: where the thing lives. For a label, the address it was given. For a vector, the slot in the vector table that holds its handler's address. |
|
||||
| Name | The label, or the vector's name. A device has no name of its own, so it is listed under its handler. |
|
||||
| File | The source file it was written in, named the way the assembler was given it. |
|
||||
| Line | Which line of that file, counting from one. |
|
||||
| Number | Which vector it is: the vector number, or the port for a device. A label has no number and the field is a dash. |
|
||||
|
||||
```
|
||||
Program 5000 start game.asm 31
|
||||
Program 670D int16add Libraries/math.asm 5
|
||||
Data 3000 Score game.asm 118
|
||||
Program 5000 start game.asm 31 -
|
||||
Program 670D int16add Libraries/math.asm 5 -
|
||||
Vector FC20 osPrintString services.asm 24 16
|
||||
Vector FC80 gameFrame game.asm 402 64
|
||||
Device FE40 diskDone system.asm 812 32
|
||||
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 kind 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.
|
||||
### Vectors In The Table
|
||||
|
||||
A vector is worth having here for two reasons that labels do not have.
|
||||
|
||||
Its number is the one thing about a program that nothing else can tell you. A vector that was pinned has its number written in the source that pinned it, but a vector the assembler numbered has that number nowhere at all: not in the source, and not in the binary in any form you can read. The table is where you find out that gameFrame became vector 64.
|
||||
|
||||
And a vector takes two hops to follow by hand. The name in `SWI osPrintString` is not the name of the routine that implements it, so finding the code means searching for the vector, reading the handler's name off the Vector Segment, and searching again. A vector's row names the handler and gives the line the two were tied together on.
|
||||
|
||||
Both of a vector's numbers are given, because neither can be worked out from the other without knowing which table the vector is in. The Number is what a program writes and what the machine dispatches on. The Address is where the handler's address is stored - 0xFC00 plus twice the number for a software vector, 0xFE00 plus twice the port for a device - which is what a loader writes and what a memory dump shows.
|
||||
|
||||
A vector that this program only declares, without implementing it, is listed like any other. That is how a program says which vectors it calls, and it is the way to check that two programs agree about a number.
|
||||
|
||||
The table is sorted by kind and then by address, in the order Program, Data, Vector, Device.
|
||||
|
||||
The assembler stops at the first error, says which file and line it was in, and exits without writing anything.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user