The vector's number goes beside its kind, not at the end of the line
Kind and Number together are what names a thing: Vector 16 and Device 32 are identifiers in a way that Vector on its own is not. Everything after them - where it lives, what it is called, where it was written - says something about it rather than naming it, so with the number at the far end a line opened with a bare kind and closed with the fact that would have told you what you were reading. Fields are now Kind, Number, Address, Name, File, Line. A label still carries a dash where its number would be, which reads as "this kind is not numbered" rather than as a field that went missing. Manual and the docs check follow. Verified with break.sh by swapping the number and the address back. 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
f3d8985bc4
commit
7dca141aae
@@ -66,6 +66,14 @@ int vectorArrayCount = 0;
|
||||
// and what a memory dump shows. Neither can be worked out from the other without knowing
|
||||
// which table it is in, so the file says both.
|
||||
//
|
||||
// THE NUMBER SITS SECOND, beside the kind rather than out at the end, because the two of
|
||||
// them together are what names the thing: "Vector 26" and "Device 32" are single identifiers
|
||||
// in the way "Vector" alone is not. Everything after them - where it lives, what it is
|
||||
// called, where it was written - is something about the thing rather than part of naming it,
|
||||
// so the line reads as an identity followed by its properties. A label has no number and
|
||||
// carries a dash in that column, which is the shape of the answer "this kind is not numbered"
|
||||
// rather than an empty space that could be a missing field.
|
||||
//
|
||||
// Sorted by kind and then address rather than by name, because the question asked of it is
|
||||
// always "what is at this address"; sorting by address alone would interleave separate
|
||||
// address spaces and make the first column flicker between them. The table is small enough
|
||||
@@ -146,17 +154,17 @@ void writeSymbolFile(const char *path) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
char number[12]; // Wide enough for any int, which is more than a vector needs.
|
||||
if (rows[i].number < 0) {
|
||||
// A LABEL HAS NO NUMBER, and the field says so rather than being left empty:
|
||||
// a run of tabs with nothing between them is the one thing a reader of this
|
||||
// file, human or otherwise, can miscount.
|
||||
// A label has no number, and the field says so rather than being left empty: a
|
||||
// run of tabs with nothing between them is the one thing a reader of this file,
|
||||
// human or otherwise, can miscount.
|
||||
snprintf(number, sizeof(number), "-");
|
||||
} else {
|
||||
snprintf(number, sizeof(number), "%d", rows[i].number);
|
||||
}
|
||||
fprintf(file, "%s\t%04X\t%s\t%s\t%d\t%s\n",
|
||||
kindName[rows[i].kind], rows[i].address, rows[i].name,
|
||||
fprintf(file, "%s\t%s\t%04X\t%s\t%s\t%d\n",
|
||||
kindName[rows[i].kind], number, rows[i].address, rows[i].name,
|
||||
rows[i].fileName ? rows[i].fileName : "?",
|
||||
rows[i].lineNumber, number);
|
||||
rows[i].lineNumber);
|
||||
}
|
||||
free(rows);
|
||||
fclose(file);
|
||||
|
||||
@@ -430,21 +430,23 @@ Every option above that takes a \<file\> names a file the assembler WRITES, and
|
||||
| Field | Meaning |
|
||||
| -- | -- |
|
||||
| Kind | Program, Data, Vector or Device. |
|
||||
| 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. |
|
||||
| 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 -
|
||||
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 -
|
||||
Program - 5000 start game.asm 31
|
||||
Program - 670D int16add Libraries/math.asm 5
|
||||
Vector 16 FC20 osPrintString services.asm 24
|
||||
Vector 64 FC80 gameFrame game.asm 402
|
||||
Device 32 FE40 diskDone system.asm 812
|
||||
Data - 3000 Score game.asm 118
|
||||
```
|
||||
|
||||
The kind and the number sit together at the front because the two of them are what names the thing: Vector 16 and Device 32 are identifiers in a way that Vector on its own is not. Everything after them says something about it rather than naming it, so a line reads as a thing followed by what is known about it.
|
||||
|
||||
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 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.
|
||||
|
||||
+4
-4
@@ -838,8 +838,8 @@ if "## Running the Assembler:" not in am:
|
||||
else:
|
||||
section = am.split("## Running the Assembler:")[1].split("\n## ")[0]
|
||||
said = [row.split(" |")[0] for row in re.findall(r'^\| (\w+ \|.*)$', section, re.M)
|
||||
if row.split(" |")[0] in ("Kind", "Address", "Name", "File", "Line", "Number")]
|
||||
if said != ["Kind", "Address", "Name", "File", "Line", "Number"]:
|
||||
if row.split(" |")[0] in ("Kind", "Number", "Address", "Name", "File", "Line")]
|
||||
if said != ["Kind", "Number", "Address", "Name", "File", "Line"]:
|
||||
problems.append("the Assembler Manual does not describe the symbol file's six"
|
||||
" fields in order; it lists %s" % (said or "none"))
|
||||
else:
|
||||
@@ -875,7 +875,7 @@ else:
|
||||
" Assembler Manual describes six"
|
||||
% (number, len(fields)))
|
||||
break
|
||||
kind, address, name, source, where, index = fields
|
||||
kind, index, address, name, source, where = fields
|
||||
kinds.add(kind)
|
||||
if kind not in ("Program", "Data", "Vector", "Device"):
|
||||
problems.append("a symbol file calls something a %r, and the"
|
||||
@@ -934,7 +934,7 @@ else:
|
||||
# drift lands on a line that has nothing to do with the name.
|
||||
sources = {}
|
||||
for row in open(dump).read().splitlines():
|
||||
kind, address, name, source, where, index = row.split("\t")
|
||||
kind, index, address, name, source, where = row.split("\t")
|
||||
if source not in sources:
|
||||
try:
|
||||
sources[source] = open(source).read().splitlines()
|
||||
|
||||
Reference in New Issue
Block a user