bd94059c08aeb3c4d49b869c36f995b788b7e9ba
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3f95056eec |
Three papercuts a visitor would hit first
Found by a review, all three confirmed by trying them rather than by reading. 1. THE STRICT BUILD CLAIM WAS FALSE. The README says the sources build clean under -std=c11 -pedantic with -Wall -Wextra, and they did not: realpath is an XSI interface, and _POSIX_C_SOURCE=200809L does not reach it, so the assembler would not compile. The ordinary -Os build never saw it, because without -std=c11 the compiler's own default declares realpath anyway. _XOPEN_SOURCE=700 is POSIX.1-2008 plus XSI, and covers every file on its own. Narrowed by compiling each source with each candidate macro rather than by adding one and hoping. And 'make strict' now checks it, as part of 'make test'. The README makes a claim somebody may check by typing it, so the suite types it. Verified the check bites by putting the old macro back. 2. THE COSMOS README HAD NOT CAUGHT UP WITH THIS WEEK. It said there were no breakpoints and proposed writing a spare byte over an instruction - two commits after SWI osBreak was built, which does it without overwriting anything and is described correctly further down the same file. Its Current Scope said there was no native assembler and that self-hosting was the intended long-term milestone. And the streaming section spoke of a machine "one day going to assemble itself". All three now say what is true. Self-hosting is described as done, with what is left of it named: a linker, and an editor that knows what assembly is. 3. 'make run-hello' DID NOT WORK, and it is the one command the makefile's own header advertises. It was a pattern rule against $(BUILD)/%.bin, which worked while every program sat at the top of Programs/ and broke the moment they were filed into Examples/ - which I did, four commits ago, without trying it. The name is looked up among the programs now, so it is the program's name rather than its path, and an unknown one lists what there is instead of saying "No rule to make target". The same sweep was run across all four documents for other claims this week invalidated. The remaining "not yet" phrases are about faults that genuinely are not defined yet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW |
||
|
|
7e8639489b |
Take the direction out of the last cross references
Includes two edits of Anachronaut's: dropping a "See the Assembler Manual" from text that is now IN the Assembler Manual, and tightening a sentence about when a vector number has to be agreed. The first of those was mine to have caught. Moving "Loading A Program From A Disk" into that manual turned a cross reference into a document telling you to go and read itself. I checked for dangling references before the move and found none, because I checked for references by SECTION NAME and not for references to the manuals themselves. Checked properly now, both directions: no other document refers to itself, and nothing that moved says "above" or "below" about something that ended up in a different file. The three remaining directional references are gone with them - two that were correct today and one, "See Numbers You Write Down below", pointing at a section twenty four lines further down that nothing guaranteed would stay there. A reference that carries a direction is a reference that goes wrong the next time anything moves, and this week moved a great deal. There are none left anywhere in the repository. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW |
||
|
|
fa3982dbd9 |
Move the CosmOS third of the Programming Manual to CosmOS
386 of the manual's 1,116 lines documented an operating system rather than a machine. The split inside that file was never tutorial against reference; it was the machine against the software that happens to run on it. What A Program May Ask The System For 129 -> CosmOS README Programs That Come With The System 111 -> CosmOS README Reading And Writing The Filesystem 64 -> CosmOS README Loading A Program From A Disk 52 -> Assembler Manual The Console Library 25 -> CosmOS README The services are the clearest case: a hundred and thirty lines describing what CosmOS offers a program, in the manual for a CPU that has no operating system of its own. A different system on the same machine would offer different services and that section would be wrong for it. The loadable program format goes to the Assembler Manual instead, because SBEX is a thing the assembler WRITES. Nothing in the CPU knows what it is. The Programming Manual is 716 lines and fourteen sections now, all of them about the machine. TWO DUPLICATE DESCRIPTIONS COLLAPSED INTO ONE EACH. The application list existed in both documents in different words, and the CosmOS copy had gone stale - no Break, no Stream, no assembler - because only the manual's copy was checked. Moving the checked one in and deleting the other leaves one list, and docs.sh follows it. The second was made by this commit and caught while reading the seams: the CosmOS README already had a service table, so the move briefly produced two. That section now says what services are for and points at the one table. Renaming a section as it moved: "Reading And Writing The Filesystem" is "The Filesystem Library", which says what it is and reads beside "The Console Library". docs.sh follows all five, and each was verified by renaming the heading in its new home and reading the complaint. The README and the CosmOS README both described what the other manuals cover, and both were wrong the moment this landed; they say the division out loud now, since it is the point. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW |
||
|
|
dcb331c151 |
SplitBit assembles SplitBit: M1, a single file with no includes
Programs/CosmOS/Assembler/ is an assembler written in SplitBit assembly. It
runs under CosmOS, reads source off a SplitBit disk, and writes a binary back
to it with no host involved anywhere:
> run Asm.sbx hello.asm
wrote hello.bin: program 17, data 14, labels 2
THE ACCEPTANCE TEST IS THE BYTES. Tests/native.sh assembles Programs/hello.asm
both ways and compares the two files byte for byte, then runs the one the
machine built. "It ran" and "the sizes look right" both pass for a binary with
a label one byte out, which is a program that jumps into the middle of an
instruction - so the only honest test is the one SplitDisk and sbfs.asm
already work under: two implementations of one written specification, each
checking the other. The files are identical and the result prints Hello,
World! in 70 cycles.
hello.asm is the target because it is the oldest program in the repository.
The first thing this machine ever ran is now the first thing it assembles for
itself.
TWO PASSES OVER STREAMED SOURCE. The C assembler reads every token of every
file into one array; that cannot port, because cosmos.asm alone is 56,047
bytes against 64K of Data Memory. The native one streams through a 256 byte
window, twice, and keeps only the label table between the passes. Two passes
suffice because every length is known without resolving anything - an
instruction's from its shape, a value's is one, a string's is its characters
and a zero - so the first pass fixes every address and the second never needs
a fixup list. A forward reference stops being a special case and becomes the
reason there are two passes at all.
The parts, each checked before anything was built on it:
source.asm characters out of a file of any size, with a line number
token.asm tokens out of characters, one character of lookahead
classify.asm what a token is, in the C assembler's order, which IS the
language: keyword, instruction, value, string, label
labels.asm names packed in an arena, four bytes of index each
numbers.asm sixteen bit arithmetic, since sbfs.asm's cannot be reached
table.asm the instruction set, generated by the same script the
monitor's copy is, and now BOTH are checked by docs.sh
readTest.asm and tokenTest.asm check the reader and the tokenizer on their
own, recorded as cosmosSource and cosmosTokens. A wrong classification does
not produce a wrong byte somewhere obvious; it produces a right looking
program of the wrong length, so it is worth catching where it happens.
WHAT IT REFUSES: #Include, #Base, #Align, #Reserve and #Vectors are refused
by name rather than ignored. Skipping a directive would produce a file that
looked right and was the wrong length, which is the worst thing an assembler
can do.
Two traps worth recording, both already known to this project and both hit
again: CALL restores A, B and DP0-DP2, so three routines returning an answer
in A had it undone by their own return; and numStep works on DP0, so three
sites that set DP1 left a pointer that never advanced.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
|
||
|
|
3d2ab34229 |
Streaming: read a file bigger than the machine's memory
osFileRead hands over a whole file, which settles anything under 64K and settles nothing above it. CosmOS's own source is above it - the sources together are 104K against 64K of Data Memory - so a machine that is going to assemble itself needs another way to ask. osFileInfo (0d26) says how many blocks a file occupies. osFileBlock (0d27) hands over one of them and says how many of its bytes belong to the file. Between them a program reads a file of any size through a buffer of 256. Blocks rather than bytes from osFileInfo is forced, not chosen: a file on a sixteen megabyte disk is up to twenty four bits long and a pointer holds sixteen. osFileBlock's count answers in DP3 for the same kind of reason - a whole block is 256 bytes, which does not fit in a register, and a count that reported it as zero would make every reader special-case the end. Nothing is kept open. Every call names the file, so there is no handle to leak and nothing left behind by a program that stops halfway. Taken at its word that means searching the directory once per block, so the system remembers where the last file it was asked about lives; every path that can change what a name means calls fileForget, including the shell's own delete and rename, which do not go through the services. Correctness never depends on the cache - a cache thrown away is indistinguishable from one never filled. Measured on a 329 block file: 7% of the run saved when the file is the first directory entry, 11% when it is the sixteenth. These two say WHY when the answer is no, which the others do not. Elsewhere the only useful response to a failure is to give up, so one value suffices. These are asked questions, and running off the end is how a reader learns it has finished, so it gets an answer of its own: 1 no disk, 2 no such file, 3 past the end, 4 the disk refused. Apps/Stream.asm reads an 84,000 byte file through 256 bytes. The check that matters is the second one: a small file read BOTH ways - whole with osFileRead and streamed - with the two checksums compared, so streaming is measured against the path already known to work rather than against a number someone wrote down. The checksum is Fletcher's rather than a sum, because a sum is the same whatever order the bytes arrived in and the order is exactly what streaming has to get right. Both checksums were also confirmed against the same arithmetic run on the host. The rest of the test is the cache: two files read alternately catch a memory that missed the name changing, and a rename catches one that missed the file moving - and that one would otherwise pass, since the blocks are still there holding the same bytes. The test file is generated rather than taken from the repository. The CosmOS sources would be a truer picture and would move the recorded checksum every time a line of CosmOS was edited, putting a real difference in a crowd of meaningless ones - the same trap the cycle counts used to set. cosmosBreak's recorded output moves by two bytes in two pointers: SbfsIndex added two bytes to the filesystem's data and Break prints the system addresses the registers happened to hold. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW |
||
|
|
3b800a69e8 |
Monitor: a line assembler
a <address>, then instructions until a line that is just a dot. The syntax is the assembler's own: a selector rides on the mnemonic as LDA.0 or LDD.0.1, and leaving one off means Data Pointer 0 exactly as it does in a source file, so nothing learned at the monitor has to be unlearned when writing a program. Case is folded, since the assembler does not care either. Numbers are hexadecimal and bare. A source file writes 0x2000 or 0d16 because it has both and must say which; a monitor has one and says so once, in the manual, rather than on every line. It reads the same table the disassembler does, searched the other way round, which is the point of it being a table rather than two lists: what a writes, d reads back, and neither can drift from the other or from the assembler both were generated from. Instruction lengths come from the shared shape table too, so the cursor cannot get out of step with what was written. THE WHOLE LINE IS UNDERSTOOD BEFORE ANYTHING IS WRITTEN. Emitting the opcode first and discovering a missing operand afterwards leaves half an instruction in memory, which the next line usually covers up and the last line of a session does not. Written that way first and fixed. What cannot be written is a label, and that is the whole difference between this and the assembler proper: a label is a promise to fill an address in later, and later is what a line at a time does not have. The recorded test now types in a complete program - a string poked into Data Memory, instructions assembled into Program Memory, and the result run - and includes a lower case mnemonic, both selector forms, an instruction that does not exist and one missing its value, so the refusals sit beside the successes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b36d438132 |
Add the CosmOS README, brought up to date with today's changes
Written by Anachronaut and not previously committed. Three things in it had
gone stale between writing and now, and are corrected here rather than
committed knowingly wrong:
- the shell command table still described dump, which the monitor
supersedes, so it now describes monitor mode and its commands
- the service table listed four services, and there are nine
- the application list did not mention Files
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|