DPUP takes an immediate, so an offset of one is legal and does exactly the right thing. It is also three bytes where INCD is two, and reads as "offset the pointer up by one" where INCD reads as "step the pointer". 56 of them across 15 files: the system, the assembler, the editor, and eight test programs. CosmOS is 9,564 bytes to 9,537, the native assembler 11,648 to 11,635, and every program in the repository together 49 bytes lighter. The worst offender was numbers.asm, written this week, where every sixteen bit helper reaches the low byte and comes back the long way round. It is the file every other part of the assembler includes, so it is the first thing anybody reads when they go looking - and it was teaching them the long way. Pattern matched off sbfs.asm rather than off the instruction table I had just embedded in two programs. THIS IS NOT TWO WAYS TO DO ONE THING. DPUP takes an arbitrary number, so one is inevitably among them; INCD earns its place by making the common case a byte cheaper. The overlap is structural and the choice is a usage question, which is a linter's job rather than an ISA's - "DPUP.n 0d01: INCD.n does this in a byte less" is a mechanical rule with no judgement in it. Nothing needed re-recording, which was not a foregone conclusion: cosmosBreak prints the system addresses the registers happened to hold, and they did not move. Both assemblers still produce identical bytes and CosmOS still builds itself to a fixed point. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
133 lines
2.6 KiB
NASM
133 lines
2.6 KiB
NASM
; Walking the directory of a SplitBit filesystem.
|
|
;
|
|
; sbfsFind answers a question about one name. This is the other thing a directory is for:
|
|
; being listed. The disk was made by SplitDisk, so the order and contents here are what
|
|
; the other implementation of the format wrote, not what this one assumed.
|
|
;
|
|
; The cases that matter are all on this disk already. There are twelve files, which is
|
|
; more than the eight an entry block holds, so the walk has to cross from the first
|
|
; directory block into the second. aName22CharactersLong! fills the name field exactly and
|
|
; so has no zero byte to end it, which is what the twenty third byte of SbfsName is for.
|
|
; empty.txt has no blocks at all.
|
|
;
|
|
; The count at the end is the proof that the walk stopped where the directory did. A walk
|
|
; that stepped its pointer only when it took an entry would loop forever on a free one,
|
|
; and one that stepped only when it skipped would hand out every eighth file.
|
|
;
|
|
; Correct output is the twelve files with their sizes, then how many there were.
|
|
|
|
#Include console.asm
|
|
#Include sbfs.asm
|
|
|
|
#Program
|
|
|
|
start:
|
|
CALL sbfsMount
|
|
BRQ mounted
|
|
SETD.0 NoMount
|
|
CALL printString
|
|
CALL newLine
|
|
HALT
|
|
|
|
mounted:
|
|
; Nothing found yet.
|
|
RSTA
|
|
SETD.0 Seen
|
|
STA.0
|
|
|
|
CALL sbfsFirst
|
|
BRI walkCheck
|
|
|
|
walkStep:
|
|
CALL sbfsNext
|
|
walkCheck:
|
|
BNQ walkDone
|
|
|
|
SETD.0 Seen
|
|
LDA.0
|
|
INCA
|
|
STA.0
|
|
|
|
SETD.0 SbfsName
|
|
CALL printString
|
|
|
|
; Line the sizes up, so a name that fills the field and a short one both read cleanly.
|
|
SETD.0 SbfsName
|
|
CALL nameWidth
|
|
MVQA
|
|
CALL printSpaces
|
|
|
|
; A file is its blocks times 256 plus its tail, which is the block count in the high
|
|
; byte and the tail in the low one. Nothing has to multiply anything.
|
|
SETD.0 SbfsFileBlocks
|
|
INCD.0
|
|
LDA.0
|
|
SETD.1 Size
|
|
STA.1
|
|
SETD.0 SbfsFileTail
|
|
LDA.0
|
|
SETD.1 Size
|
|
INCD.1
|
|
STA.1
|
|
|
|
SETD.0 Size
|
|
CALL printWordDecimal
|
|
CALL newLine
|
|
BRI walkStep
|
|
|
|
walkDone:
|
|
SETD.0 Total
|
|
CALL printString
|
|
SETD.0 Seen
|
|
LDA.0
|
|
CALL printByteDecimal
|
|
CALL newLine
|
|
HALT
|
|
|
|
; DP0 names a string. Q is how many spaces would pad it out to twenty four characters.
|
|
; A name that is already that long gets one space, because none at all would run the
|
|
; name into the number.
|
|
nameWidth:
|
|
INIA 0d24
|
|
SETD.1 Padding
|
|
STA.1
|
|
widthLoop:
|
|
LDA.0
|
|
BRA widthDone
|
|
SETD.1 Padding
|
|
LDA.1
|
|
DECA
|
|
STA.1
|
|
BRA widthFloor ; It is already too long to pad.
|
|
INCD.0
|
|
BRI widthLoop
|
|
widthFloor:
|
|
INIA 0d1
|
|
SETD.1 Padding
|
|
STA.1
|
|
widthDone:
|
|
SETD.1 Padding
|
|
LDA.1
|
|
RSTB
|
|
CCF
|
|
ADD
|
|
RET
|
|
|
|
#Data
|
|
|
|
NoMount:
|
|
"no filesystem on that disk"
|
|
Total:
|
|
"files: "
|
|
|
|
Seen:
|
|
0x00
|
|
Padding:
|
|
0x00
|
|
Size:
|
|
0x00 0x00
|
|
|
|
#Vectors
|
|
|
|
Boot start
|