CosmOS: a service interface for the disk and console, and the monitor in the shell
Two changes that arrived together because both live in cosmos.asm. THE SERVICES. A loaded program that wanted a file had to include the whole filesystem, carrying two and a half kilobytes of a private copy of code the system already had running, and then mount a disk that was already mounted. Five services are added at pinned numbers 20 to 24: osFileRead, osFileSave, osFileDelete, osFileRename and osPrintNumber. The sizes fit the registers exactly in both directions. A file that can be read into Data Memory is under 64K by definition, so its length is sixteen bits: coming back it is DP3, going out it is A and B together, and neither direction needs a record in memory whose shape both sides must agree on. There is deliberately no service to mount a disk. The system mounts one before its first prompt, and a program mounting it again was only ever a consequence of owning a second copy of the library, so that call disappears rather than moving. Apps/Files.asm writes, reads, renames and deletes a file in 645 bytes and includes nothing but the service names. THE MONITOR. Previously an application, now part of the shell, because an application occupies the one region a loaded application is given: a monitor that was an application could never examine another one, since loading the thing to be inspected would replace the thing doing the inspecting. "monitor" turns it on and the prompt becomes "*". It is a mode rather than a sub-prompt, and it persists: because the mode is a variable the prompt reads rather than a second loop, and every path back to the prompt goes through one place including osExit, a program started with "g" that gives the machine back arrives at the monitor prompt it was started from. Examining a program and running it therefore do not interrupt each other. "exit" leaves whatever you are in. It supersedes dump, and adds disassembly, writing bytes, and jumping to an address. Its instruction table is generated from the assembler's own list by Tests/instructiontable.py rather than typed again, and Tests/docs.sh checks both that the system's copy matches the generator and that the lengths that table implies are the ones the manual's Bytes column prints. A disassembler that disagreed about a length would not print one line wrong, it would lose its place and print everything after it wrong. Also here: b refuses a bank that is not registered, since asking the controller for one is refused and a refusal nobody catches stops the machine; g records the Stack the way run does, without which a program returning through osExit restored whatever the last run had left; and make cosmos-disk now depends on the system as well as the image. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
301716e869
commit
0b6d2be43f
@@ -0,0 +1,176 @@
|
||||
; A program that keeps a file without knowing how a filesystem works.
|
||||
;
|
||||
; INCLUDES NOTHING BUT THE SERVICE NAMES. No sbfs.asm, no console.asm - the system has both
|
||||
; of those running already, and this asks it rather than carrying a second copy. That is the
|
||||
; whole point of the program: if it works, a tool that edits documents does not need two and
|
||||
; a half kilobytes of filesystem bound into it.
|
||||
;
|
||||
; It writes a file, reads it back, says how big it was, renames it, and takes it away again,
|
||||
; which is every file service there is.
|
||||
;
|
||||
; ---- What you will see before the handlers are written ----
|
||||
;
|
||||
; The numbers are pinned but nothing answers to them yet, so the first call dispatches
|
||||
; through an empty vector and the machine stops:
|
||||
;
|
||||
; Fault: Software vector 21, dispatched from Program Address 0x200B, has no handler
|
||||
; installed.
|
||||
;
|
||||
; That is the fault working properly rather than the program being broken. A vector with
|
||||
; nothing in it is not a jump to address zero; it is a stop, with the vector named and the
|
||||
; place it was called from named, which is as much as the machine can know.
|
||||
|
||||
#Include services.asm
|
||||
|
||||
#Program
|
||||
|
||||
#Base 0x2000
|
||||
|
||||
start:
|
||||
; ---- Write it ----
|
||||
;
|
||||
; A and B together are how many bytes there are, most significant first, which is the
|
||||
; same sixteen bits a length always is on this machine.
|
||||
SETD.0 Name
|
||||
SETD.1 Body
|
||||
RSTA
|
||||
INIB 0d22 ; The text and its newline. NOT the zero the assembler put
|
||||
SWI osFileSave ; after it: a text file ends where the text ends.
|
||||
BNQ noSave
|
||||
SETD.0 SavedText
|
||||
SWI osPrintString
|
||||
|
||||
; ---- Read it back ----
|
||||
;
|
||||
; DP3 comes back holding how many bytes there were, because that is one of the two things
|
||||
; a service is allowed to answer in and a file that fits in memory has a length that fits
|
||||
; in a pointer.
|
||||
SETD.0 Name
|
||||
SETD.1 Landing
|
||||
SWI osFileRead
|
||||
BNQ noRead
|
||||
SETD.0 ReadText
|
||||
SWI osPrintString
|
||||
|
||||
PSHD.3
|
||||
POPB ; The low byte is on top, the way a pointer is pushed.
|
||||
POPA
|
||||
SWI osPrintNumber
|
||||
SETD.0 BytesText
|
||||
SWI osPrintString
|
||||
|
||||
; And now the length is needed for something rather than just reported. What came back is
|
||||
; a file, not a string: nothing on the disk ends in a zero byte, because the entry says
|
||||
; where it stops instead. So a zero goes on the end before it can be printed as one.
|
||||
SETD.1 Landing
|
||||
PSHD.3
|
||||
POPB
|
||||
POPA
|
||||
walkToEnd:
|
||||
BRB atEnd
|
||||
INCD.1
|
||||
DECB
|
||||
BRI walkToEnd
|
||||
atEnd:
|
||||
RSTA
|
||||
STA.1
|
||||
|
||||
SETD.0 Landing
|
||||
SWI osPrintString
|
||||
|
||||
; ---- Call it something else ----
|
||||
SETD.0 Name
|
||||
SETD.1 OtherName
|
||||
SWI osFileRename
|
||||
BNQ noRename
|
||||
SETD.0 RenamedText
|
||||
SWI osPrintString
|
||||
|
||||
; ---- And take it away ----
|
||||
SETD.0 OtherName
|
||||
SWI osFileDelete
|
||||
BNQ noDelete
|
||||
SETD.0 DeletedText
|
||||
SWI osPrintString
|
||||
|
||||
; Reading it now should fail, and a service saying no is not the same as one that is not
|
||||
; there: this comes back with an answer rather than stopping the machine.
|
||||
SETD.0 OtherName
|
||||
SETD.1 Landing
|
||||
SWI osFileRead
|
||||
BRQ stillThere
|
||||
SETD.0 GoneText
|
||||
SWI osPrintString
|
||||
SWI osExit
|
||||
|
||||
stillThere:
|
||||
SETD.0 StillText
|
||||
SWI osPrintString
|
||||
SWI osExit
|
||||
|
||||
noSave:
|
||||
SETD.0 NoSaveText
|
||||
SWI osPrintString
|
||||
SWI osExit
|
||||
noRead:
|
||||
SETD.0 NoReadText
|
||||
SWI osPrintString
|
||||
SWI osExit
|
||||
noRename:
|
||||
SETD.0 NoRenameText
|
||||
SWI osPrintString
|
||||
SWI osExit
|
||||
noDelete:
|
||||
SETD.0 NoDeleteText
|
||||
SWI osPrintString
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
#Base 0x1000
|
||||
|
||||
Name:
|
||||
"kept.txt"
|
||||
OtherName:
|
||||
"moved.txt"
|
||||
|
||||
Body:
|
||||
"a file kept by asking
|
||||
"
|
||||
|
||||
SavedText:
|
||||
"saved it
|
||||
"
|
||||
ReadText:
|
||||
"read it back, "
|
||||
BytesText:
|
||||
" bytes:
|
||||
"
|
||||
RenamedText:
|
||||
"renamed it
|
||||
"
|
||||
DeletedText:
|
||||
"deleted it
|
||||
"
|
||||
GoneText:
|
||||
"and it is gone
|
||||
"
|
||||
StillText:
|
||||
"but it is still there
|
||||
"
|
||||
|
||||
NoSaveText:
|
||||
"it would not save
|
||||
"
|
||||
NoReadText:
|
||||
"it would not read
|
||||
"
|
||||
NoRenameText:
|
||||
"it would not rename
|
||||
"
|
||||
NoDeleteText:
|
||||
"it would not delete
|
||||
"
|
||||
|
||||
Landing:
|
||||
#Reserve 0d256
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,3 +25,29 @@
|
||||
osReadLine 0d17 ; DP0 names somewhere to put a line read from the console.
|
||||
osExit 0d18 ; Give the machine back to the system.
|
||||
osArgument 0d19 ; DP0 names somewhere to put the rest of the run command.
|
||||
|
||||
; ---- What the system does with the disk on a program's behalf ----
|
||||
;
|
||||
; A loaded program that wanted a file used to include the whole filesystem, which is two
|
||||
; and a half kilobytes of it carrying a private copy of code the system already has
|
||||
; running. These are that code, reachable.
|
||||
;
|
||||
; NOTHING HERE MOUNTS ANYTHING. The system mounted the disk before it read the prompt, and
|
||||
; there is one disk with one buffer registered as one bank; a program mounting it again was
|
||||
; only ever an artefact of having its own copy of the library.
|
||||
;
|
||||
; Sizes are in bytes and fit the registers exactly. A file that can be read into Data
|
||||
; Memory is under 64K by definition, so its length is sixteen bits: coming back it is DP3,
|
||||
; going out it is A and B together, and neither direction needs a record in memory that
|
||||
; both sides have to agree on the shape of.
|
||||
osFileRead 0d20 ; DP0 names it, DP1 says where. Q is zero if it read, DP3 is how many bytes.
|
||||
osFileSave 0d21 ; DP0 names it, DP1 is the bytes, A and B are how many. Q is zero if it saved.
|
||||
osFileDelete 0d22 ; DP0 names it. Q is zero if it went.
|
||||
osFileRename 0d23 ; DP0 is the name it has, DP1 the name it should have. Q is zero if it moved.
|
||||
|
||||
; ---- And with the console ----
|
||||
;
|
||||
; printString is already up there. This is the other half of what a program prints: a
|
||||
; number, in decimal, without leading zeroes. A and B together, so one service covers both
|
||||
; a line number and a byte count and there is no need for two.
|
||||
osPrintNumber 0d24
|
||||
|
||||
+4
-1
@@ -79,7 +79,10 @@ $(COSMOS_DISK): $(APPS)
|
||||
$(DISKTOOL) format $@ 256 2
|
||||
@for app in $(APPS); do $(DISKTOOL) put $@ $$app; done
|
||||
|
||||
cosmos-disk: $(COSMOS_DISK)
|
||||
# The system as well as the disk. Building only the image leaves whatever cosmos.bin was
|
||||
# there before, or none at all, and then the disk is booted with a system that does not
|
||||
# match the programs on it.
|
||||
cosmos-disk: $(COSMOS) $(COSMOS_DISK)
|
||||
|
||||
run-cosmos: $(COSMOS) $(COSMOS_DISK)
|
||||
$(EMU) --disk $(COSMOS_DISK) $(COSMOS)
|
||||
|
||||
Reference in New Issue
Block a user