Files
SplitBit-Emulator/Programs/CosmOS/Assembler/scratch.asm
T
AnachronautandClaude Opus 5 563bc20a75 Tab lists its matches in columns, and says what it can in colour
Tab's listing was six instructions: print the name, print two spaces. It
was the crown of this shell for a while and looks plain next to ls.

Columns cost NOTHING EXTRA. Tab already walks its candidates twice - once
to find the answer, once to show the matches, and tabRunSources exists
because those are the same walk asked two questions. The longest match is
counted on the first, which already visits every one of them, so the
listing needs no walk of its own to know how wide a column should be.
Padding goes before a name rather than after, so a row ends on a name.

Directories are blue and the shell's own commands are green. Both are
free: Tab appends the separator itself, and a built-in is not a file at
all - which is also the only way anybody could know it will run.

A FILE IS NOT COLOURED, and that is a decision. Whether a file will run
is a read of its first block, which is what ls does and what makes ls
cost twice what it otherwise would. Here it would be worse than slow:
candidates are offered from inside a directory walk, and looking a file
up would overwrite the very fields holding the walk's own position. Doing
it safely means holding every candidate name in memory, which is a buffer
the shell would carry whether anybody pressed Tab or not - and ls is one
keystroke away. A Tab press already costs about 200,000 cycles, so the
read was not the objection.

---- And the machine could no longer build itself ----

Found by make test, not by reading. The native assembler ran out of room
for label names on cosmos.asm: 16,758 bytes against 16,384. The index was
1,341 of 1,536 in the same breath.

Which is scratch.asm's own warning happening a second time - "two
ceilings a hundred bytes apart look like one ceiling until the first is
lifted" - so both were raised, out of the seventeen kilobyte page that
file deliberately left unclaimed against exactly this. Names to 26,624
and the index to 2,048, both left about a third clear, with 1,792 bytes
still unclaimed for the same reason.

A name is thirteen bytes on average and an index entry is four, so the
arena will always be the one that speaks first. That is now written down
where the two numbers are.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
2026-09-06 20:18:56 -04:00

109 lines
6.0 KiB
NASM

; Where the assembler's big buffers live.
;
; A map rather than a set of declarations, and it has a file of its own because the reader
; and the label table both need addresses out of it while neither includes the other.
;
#Data
; NOT #Reserve, AND THAT IS THE WHOLE POINT. Reserved space in a segment is written into
; the file as zeroes and copied at load, so 22K of scratch made a 34K file - and a loaded
; program is staged at 0x8000 before being put in place, which leaves exactly 32,768 bytes
; for the whole of it. The assembler could not load itself.
;
; None of this is initialised data. It is scratch, wanted only while the assembler is
; running, and while it is running everything above its own data is free: the system keeps
; below 0x2FFF, the staging area is only in use during a load, and the Stack comes down
; from the top. So the addresses are written down here and the file carries none of it.
;
; That sentence said 0x1000 for a while after the system's half of Data Memory was
; doubled, twelve lines above the paragraph that explains the doubling. A stale number is
; bad enough; a stale number sitting next to the correction is worse, because whichever
; one a reader takes is a coin toss.
;
; 0x5000 8192 the label index, 2048 entries of four
; 0x7000 26624 the label names, packed end to end
; 0xD800 256 one block of the output file, on its way to the disk
; 0xD900 1792 free
; 0xE000 1792 the vector names, 64 entries of twenty eight
; 0xE700 2048 the reader's stack, six levels of 301
; 0xEF00 368 which files have been included, sixteen names of 23
;
; IT USED TO START AT 0x8000, and the reason given was that everything above the
; assembler's own data is free. That was true when it was written and stopped being true
; without anything noticing: the system kept below 0x1000 then, and its data now reaches
; 0x1FFF, and the assembler's own moved from 0x1000 to 0x2000 with it. The floor came up
; and the map stayed where it was, leaving sixteen kilobytes between the two that nothing
; touched.
;
; Starting above the assembler's own data takes that back. It began at 0x4000 with the data
; from 0x2000, and moved to 0x5000 when the system was given another page and every
; application's data moved to 0x3000 with it - THE FLOOR CAME UP A SECOND TIME, exactly as
; the paragraph above says it did the first, and this time the check below said so before
; anything ran: the assembler's data reached 0x40D6 and the index began at 0x4000, so the
; buffers were sitting on the variables.
;
; There is still nearly four kilobytes of slack in front of this, and room for the data to
; double before the two would meet. `make test` measures that gap now
; rather than trusting this paragraph, and measures the floor above as well, because both
; of those numbers describe the machine AROUND this file and neither is enforced by a line
; of code anywhere.
;
; THE ROOM WENT TO ALL THREE OF THE BUFFERS THAT WERE FULL, and there turned out to be
; three rather than one. The output was the obvious wall - cosmos.bin was 13,245 bytes
; against 13,312, which is sixty seven - so it was given the lot, and the very next thing
; added to the system ran out of LABEL NAMES instead, at 8,081 of 8,192. Two ceilings a
; hundred bytes apart look like one ceiling until the first is lifted.
;
; The index was a hundred and eighteen entries from the same place. So: names doubled,
; index doubled, and the output given what is left, which is still four and a half thousand
; bytes more than CosmOS needs today.
;
; THE OUTPUT IS NO LONGER HELD AT ALL. It used to be built whole in memory and handed over
; at the end, which is what made a buffer of eighteen kilobytes the largest thing this
; machine could assemble. The file is produced in order, so it is written as it is made,
; through one block of window - and the eighteen kilobytes that were its share are free.
;
; What to do with them is not obvious and does not have to be decided today. Nothing here
; is close to full: the names are at half, the index at a third, and the output has no
; ceiling of its own any more. Leaving the room unclaimed is better than sharing it out
; among buffers that do not need it, because an unclaimed page is available to whichever
; one turns out to want it.
;
; ---- And one turned out to want it ----
;
; Sixteen kilobytes of names was half full when that was written and ran out on 2026-09-06,
; on an ordinary day's work on the shell: 16,758 bytes of name against 16,384. The index was
; 1,341 of 1,536 in the same breath, which is the paragraph above this one happening again -
; two ceilings, and lifting only the one that spoke would have bought two hundred labels.
;
; So both, out of the free page, and both left at about a third clear rather than at half:
; the names to 26,624 and the index to 2,048. What is left over is 1,792 bytes, kept
; unclaimed for the same reason the seventeen kilobytes were.
;
; That ends at 0xF070, with the Stack coming down from 0xFFFF above it - nearly four
; kilobytes, against the tens of bytes of CALL frames this ever nests.
;
; The reader's levels went from 293 to 301 when an include gained somewhere to be looked
; for: the name in each level is a PATH now, and "/Lib/" is five characters of it. Six
; levels of 301 is 1806, so the room here has to stay above that - which is why the include
; list moved up rather than the stack simply being asked to fit.
;
; THE TWO THINGS THAT DECIDE THESE SIZES are the largest program it will be asked to build
; and the largest one it will be asked to read. Measured 2026-09-06: CosmOS is 1,341 labels
; and 16,758 bytes of name, and the assembler itself is far smaller. It was the other way
; round when this file was written - "the hardest thing this assembles is not the operating
; system, it is itself" - and the system has grown past it since. The numbers here are worth
; measuring again rather than believing, which is why they carry a date.
ScratchLabIndex:
0x50 0x00
ScratchLabArena:
0x70 0x00
ScratchWindow:
0xD8 0x00
ScratchVecNames:
0xE0 0x00
ScratchSrcStack:
0xE7 0x00
ScratchIncNames:
0xEF 0x00