"Binary" was doing three jobs. It meant an SPBT file that the machine starts
from; it meant whatever the assembler happened to produce, which is now
either that or a loadable program; and it meant a compiled host tool. A word
that means three things means none of them, and the first of the three has a
name already - this project has been calling them boot images for a while
and the manuals had not caught up.
Where it means an SPBT file -> boot image
Where it means either output -> output
Where it means a host executable -> left alone
Where it means base two -> left alone
The user facing messages move with it:
Error: No boot image specified.
Usage: ./SplitBit [OPTIONS] <boot image>
Error: This is not a SplitBit boot image.
Error: This boot image is in format version 2, and this emulator reads 1.
Successfully wrote SplitBit boot image to "hello.bin".
The assembler's own help was the interesting case. Its -o writes either
format, so "the binary" there was never right - it is "the output" now, and
the message that names the format is the one that says which it wrote.
No recorded output contained the word, so nothing needed re-blessing.
Checked before starting rather than after.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
The quotes are gone by the time a token is classified, so checkIfKeyword's
test of token[0] == '#' matched the STRING "#Program" sitting in a program's
Data Segment. It was read as the directive: the segment silently changed in
the middle of the data, the string's nine bytes were charged to the Program
cursor instead of the Data one, and every label defined after it came out
nine bytes wrong - in a file that still had a valid header, a plausible
length, and nothing to say about any of it. The only symptom was a program
that jumped into the middle of an instruction.
This is the FOURTH of the family. A string spelling a mnemonic assembled as
that instruction; a string beginning with a zero was rejected as a malformed
literal; a string in the Program Segment was discarded in silence. The
instruction check and the literal check both carry a "not a STRING" guard
already. This one did not, so it has one now, and it lives inside
checkIfKeyword rather than at the call site so it cannot be left off again.
Nothing had ever triggered it, because nothing had ever needed a directive's
name as data. An assembler written FOR this machine necessarily does: it has
to compare tokens against "#Program" and "#Data". It was found by building
one and watching it fault on its second instruction.
Test stringKeyword puts every directive name in a program's data and prints
a label defined after them. Verified that it bites: without the fix the
assembler refuses the file outright.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
A token is classified after its quotes have been stripped, so a string
literal reading "ADD" looked exactly like the ADD instruction and was
assembled as one. It failed with "attempting to assemble outside the
Program Segment", a message about a mistake nobody had made.
The literal and label checks were already guarded against strings and the
instruction check was not. Mnemonics match without regard to case, so
"or" and "and" were caught by this too, and those are ordinary enough
words to want in a message.
Third of its family, after a string beginning with '0' being read as a
malformed number and a string in the Program Segment being silently
discarded. All three have the same root.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The loadable program format's header has been in the working tree since
the loader was written and has never been in the repository: the gitignore
rules matched Source/Assembler as a directory, so it was silently
untracked. Anything cloning this repository could not build it, because
secondPass.c includes this file.
This is the failure the previous commit describes, having already happened
once without being noticed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Added DPUP and DPDN, which take a one byte operand specifying how far up or down to offset the Data Pointer.
Three Fibonacci generators using the print.asm library.
- 8 bit values printing in decimal representation.
- 16 bit values printing in hexadecimal representation.
- 32 bit values printing in hexadecimal representation.