The memory map gave CosmOS 0x0000 through 0x1FFF of Program Memory and applications 0x2000 and above. CosmOS is 8141 bytes at the previous commit, which is fifty one bytes short of the line, and the next thing added to it went over. GOING OVER DOES NOT FAIL WHERE IT HAPPENS. Nothing enforces the division: an application says where it goes with #Base and the loader puts it there, so a CosmOS that has grown past 0x1FFF simply has the next program loaded written over the end of it. What breaks is whichever part of the shell that program happened to cover, at whatever later moment somebody uses it. It turned up here as the monitor's assemble command answering "I do not know" to valid instructions, several commands into a session, on a machine that had booted perfectly well. Both halves are doubled: applications now start at 0x4000 in Program Memory and 0x2000 in Data Memory. That is 16K of code and 8K of data for the system, against the 8775 and 2948 it uses today. Both were on the same trajectory, and moving them together means the twenty files that say #Base are edited once rather than twice. The standalone loader's loadable.asm keeps its old base: it belongs to the loader CosmOS grew out of, not to CosmOS, and its addresses answer to a different program. The unbased-segment diagnostic keeps its old base too - it exists to produce an error message that names the address, and the message is what is recorded. Tests/docs.sh now reads the two limits out of the table in the README and measures both segments against them. It reads them rather than being told them because the table is the specification, and this is the second time in this project that the thing nobody checked is the thing that rotted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
102 lines
2.7 KiB
NASM
102 lines
2.7 KiB
NASM
; A loaded program that is interrupted by the console rather than asking it for anything.
|
|
;
|
|
; Until the loadable program format could carry vectors, this could not be written. A
|
|
; handler has to be an address in the vector table, and a program that is not the one the
|
|
; machine booted from had no way to say what its vectors were, so interrupts belonged to
|
|
; boot images and every loaded program had to poll. Snake polls for exactly that reason.
|
|
;
|
|
; What this shows is the whole path: the assembler writes the vectors into the file, the
|
|
; system installs them when the program is run, the console raises its line, the handler
|
|
; runs, and the system takes the vectors back out again when the program gives the machine
|
|
; back. Nothing in the waiting loop below looks at the console at all.
|
|
;
|
|
; The vector is named by port, because a device interrupts on the port it is plugged into
|
|
; and the console is on port 0x00.
|
|
|
|
#Include services.asm
|
|
|
|
#Program
|
|
|
|
#Base 0x4000
|
|
|
|
start:
|
|
CIF ; Nothing arrives until there is something to catch it.
|
|
|
|
; Set rather than trusted to be zero. Running a program a second time does not load it
|
|
; again, so its Data Segment is exactly as the last run left it - and the last thing the
|
|
; last run did was set this.
|
|
RSTA
|
|
SETD.0 Stopping
|
|
STA.0
|
|
|
|
SETD.0 Banner
|
|
CALL printString
|
|
CALL newLine
|
|
|
|
; Key mode and interrupt on input, in one write, since the two control bits are
|
|
; independent of each other.
|
|
INIA 0x03
|
|
OUTA 0x02
|
|
SIF
|
|
|
|
wait:
|
|
; This loop is the point. It never touches the console, so every character that appears
|
|
; below was put there by something that interrupted it.
|
|
SETD.3 Stopping
|
|
LDA.3
|
|
RSTB
|
|
OR
|
|
BRQ wait
|
|
|
|
CALL newLine
|
|
RSTA
|
|
OUTA 0x02 ; Line mode and no interrupts, the way it was found.
|
|
SETD.0 DoneText
|
|
CALL printString
|
|
CALL newLine
|
|
SWI osExit
|
|
|
|
; Entered because the console had something to say. Never called.
|
|
keyHandler:
|
|
INA 0x01
|
|
INIB 0x01 ; READY: is there a byte, as opposed to the end of input?
|
|
AND
|
|
BRQ keyNoByte
|
|
INA 0x00
|
|
|
|
INIB 0x71 ; q, which is how this program is stopped.
|
|
XOR
|
|
BRQ keyStop
|
|
|
|
OUTA 0x00 ; Nothing echoes in key mode, so the handler does it.
|
|
RETI
|
|
|
|
keyNoByte:
|
|
; The end of input raises the line once as well, so a program driven entirely by
|
|
; interrupts is told when nothing more is coming instead of waiting for ever.
|
|
keyStop:
|
|
SETD.3 Stopping
|
|
INIA 0x01
|
|
STA.3
|
|
RETI
|
|
|
|
#Data
|
|
|
|
#Base 0x2000
|
|
|
|
Banner:
|
|
"keys, by interrupt. q stops."
|
|
DoneText:
|
|
"the console has been handed back"
|
|
|
|
; The only thing the handler and the loop it interrupts have to say to each other.
|
|
Stopping:
|
|
0x00
|
|
|
|
#Vectors
|
|
|
|
Boot start
|
|
Device 0x00 keyHandler
|
|
|
|
#Include console.asm
|