Give Programs/ one rule: a directory per kind, nothing loose

Five .asm files sat at the top of Programs/ beside six directories, with
nothing to say which a new file should join - and hello.asm, which is the
native assembler's first target and named in sixteen places, looked like a
stray.

    Programs/
      Examples/     what you read to learn: hello, printHello, inputTest,
                    replCalculator, and Fibonacci, primeSieve and gameOfLife
                    as sets of their own
      Libraries/    included by name, no entry point of their own
      Loader/       loader.asm, and the loadable program it reads
      CosmOS/       the system, its applications and its assembler
      testPrograms/ what 'make test' drives

Loader/ is the one worth explaining. loader.asm is not a demonstration: it
reads a program off a disk, puts the two pieces where the header asks, and
jumps to the entry. CosmOS grew out of it and does the same thing as one of
its commands. It is kept because backward compatibility with the simplest
version of the system is a standing goal, and it was sitting loose next to
the demos as though it were one.

Programs/loadable/ was a directory holding one file called hello.asm - a
third thing of that name, and the name said nothing about why it was there.
It is Loader/loadable.asm now, beside the loader that reads it.

Every reference moved with them: the makefile's program list, twelve
manifest lines, makedisks.sh, native.sh, and four paths across the README
and both manuals. Verified by deleting both build directories and running
the whole suite from nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-08-21 13:38:47 -04:00
co-authored by Claude Opus 5
parent 6dbb38b209
commit ccf4b384e1
21 changed files with 41 additions and 37 deletions
+410
View File
@@ -0,0 +1,410 @@
; Interactive hexadecimal calculator for SplitBit.
;
; Enter expressions as:
; HH operator HH
; Whitespace is optional. Supported operators are + - * & | and ^.
; Arithmetic wraps to eight bits. Enter Q to quit.
#Include print.asm
#Program
start:
SETD Welcome
CALL printString
repl:
SETD Prompt
CALL printString
CALL readNonSpace
PSHQ
POPA
; Q, q, or end-of-file exits.
INIB 0xFF
XOR
BRQ quit
INIB 0x51
XOR
BRQ quit
INIB 0x71
XOR
BRQ quit
CALL readHexByteFirst
SETD LeftOperand
STQ
CALL parseIsInvalid
BRQ inputError
CALL readNonSpace
PSHQ
POPA
SETD Operator
STA
CALL readNonSpace
PSHQ
POPA
CALL readHexByteFirst
SETD RightOperand
STQ
CALL parseIsInvalid
BRQ inputError
CALL discardLine
CALL evaluate
SETD Result
STQ
CALL operatorIsInvalid
BRQ operatorError
SETD Result
LDA
CALL printByteHex
CALL lineFeed
BRI repl
inputError:
CALL discardLine
SETD BadInput
CALL printString
BRI repl
operatorError:
SETD BadOperator
CALL printString
BRI repl
quit:
SETD Goodbye
CALL printString
HALT
; Read a character other than space, tab, CR, or LF. Return it in Q.
readNonSpace:
readNonSpaceLoop:
INA 0x00
INIB 0x20
XOR
BRQ readNonSpaceLoop
INIB 0x09
XOR
BRQ readNonSpaceLoop
INIB 0x0A
XOR
BRQ readNonSpaceLoop
INIB 0x0D
XOR
BRQ readNonSpaceLoop
INIB 0x00
CCF
ADD
RET
; A contains the first hexadecimal digit. Read the second and return the byte
; in Q. Q is 0xFF on malformed input.
readHexByteFirst:
CALL clearParseStatus
CALL hexNibble
PSHQ
POPA
INIB 0xFF
XOR
BRQ invalidByte
INIB 0x00
SHL
SHL
SHL
SHL
PSHA
CALL readNonSpace
PSHQ
POPA
CALL hexNibble
PSHQ
POPA
INIB 0xFF
XOR
BRQ invalidLowNibble
POPB
OR
RET
invalidLowNibble:
POPB
invalidByte:
PSHD
SETD ParseStatus
INIA 0x01
STA
POPD
INIA 0xFF
INIB 0x00
CCF
ADD
RET
; Convert the ASCII hexadecimal digit in A to a value in Q.
; Uppercase and lowercase letters are accepted. Q=0xFF means invalid.
hexNibble:
PSHA
; Try 0 through 9.
INIB 0x30
CCF
SUB
BRC tryUpperHex
PSHQ
POPA
INIB 0d10
CCF
SUB
BRC decimalNibble
tryUpperHex:
POPA
PSHA
INIB 0x41
CCF
SUB
BRC tryLowerHex
PSHQ
POPA
INIB 0d06
CCF
SUB
BRC upperNibble
tryLowerHex:
POPA
PSHA
INIB 0x61
CCF
SUB
BRC badNibble
PSHQ
POPA
INIB 0d06
CCF
SUB
BRC lowerNibble
badNibble:
POPA
INIA 0xFF
INIB 0x00
CCF
ADD
RET
decimalNibble:
POPB
INIB 0x00
CCF
ADD
RET
upperNibble:
POPB
INIB 0d10
CCF
ADD
RET
lowerNibble:
POPB
INIB 0d10
CCF
ADD
RET
; Return Q=0 if Q was 0xFF, otherwise return a nonzero value.
resultIsInvalid:
PSHQ
POPA
INIB 0xFF
XOR
RET
clearParseStatus:
PSHD
SETD ParseStatus
RSTA
STA
POPD
RET
parseIsInvalid:
PSHD
SETD ParseStatus
LDA
INIB 0x01
XOR
POPD
RET
operatorIsInvalid:
PSHD
SETD OperatorStatus
LDA
INIB 0x01
XOR
POPD
RET
; Evaluate the stored expression and return its result in Q.
evaluate:
PSHD
SETD OperatorStatus
RSTA
STA
POPD
SETD Operator
LDA
INIB 0x2B
XOR
BRQ evaluateAdd
INIB 0x2D
XOR
BRQ evaluateSubtract
INIB 0x2A
XOR
BRQ evaluateMultiply
INIB 0x26
XOR
BRQ evaluateAnd
INIB 0x7C
XOR
BRQ evaluateOr
INIB 0x5E
XOR
BRQ evaluateXor
SETD OperatorStatus
INIA 0x01
STA
RSTA
INIB 0x00
CCF
ADD
RET
evaluateAdd:
SETD LeftOperand
LDA
INCD
LDB
CCF
ADD
RET
evaluateSubtract:
SETD LeftOperand
LDA
INCD
LDB
CCF
SUB
RET
evaluateAnd:
SETD LeftOperand
LDA
INCD
LDB
AND
RET
evaluateOr:
SETD LeftOperand
LDA
INCD
LDB
OR
RET
evaluateXor:
SETD LeftOperand
LDA
INCD
LDB
XOR
RET
evaluateMultiply:
RSTA
SETD Product
STA
multiplyLoop:
SETD RightOperand
LDA
BRA multiplyDone
DECA
STA
SETD Product
LDA
SETD LeftOperand
LDB
CCF
ADD
SETD Product
STQ
BRI multiplyLoop
multiplyDone:
SETD Product
LDA
INIB 0x00
CCF
ADD
RET
; Consume the rest of the current input line.
discardLine:
discardLoop:
INA 0x00
INIB 0x0A
XOR
BRQ discardDone
INIB 0xFF
XOR
BRQ discardDone
BRI discardLoop
discardDone:
RET
#Data
LeftOperand:
0x00
RightOperand:
0x00
Operator:
0x00
Product:
0x00
Result:
0x00
ParseStatus:
0x00
OperatorStatus:
0x00
Welcome:
"SplitBit calculator (+ - * & | ^), Q quits."
Prompt:
0x0A
"> "
BadInput:
"Invalid hexadecimal input."
BadOperator:
"Unknown operator."
Goodbye:
"Goodbye!"
0x0A