SWI osExit takes a status in A, and the shell keeps it. Fifty eight exits across twenty three programs now say deliberately whether they worked: 25 did what they were asked, 24 did not, 9 were asked wrongly. Compare is the exception and says so - one there means the files differ, which is a result rather than a failure, the way diff has always had it. IN A RATHER THAN Q, which is not a departure from the rule that a service answers in Q. This one takes an ARGUMENT, the way osPrintNumber takes A and B, and it never returns to answer anything. A is free precisely because a return would have put it back - and Q is the ALU's output, so a small number costs four instructions there against one in A. The shell does not print it. A program that failed has already said so in words and a number beside that is noise, so osLastStatus hands it back and Status is the program that shows it. That indirection is the point: the number exists for the thing that cannot read words. MARKING THE EXITS FOUND A DEFECT ON THE FIRST RUN. Type and More printed why they had failed and then fell through into the success exit, reporting that all was well. Nobody had noticed, because while the only reader was a person, the person could see both the complaint and the claim. Two smaller things. Snake sets the console to line mode and then exits with zero, and the linter flagged the second RSTA as redundant - an exit status and a console mode, equal by accident, which is the class that must never be collapsed. And the README still taught answering by writing into the frame, three months of habit that SRET replaced yesterday; that section is gone and the one describing SRET stands in its place.
105 lines
2.9 KiB
NASM
105 lines
2.9 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
|
|
|
|
; Called spin rather than wait because WAIT is an instruction now, and a label may not
|
|
; be one. Which is the joke of it: this loop is exactly what WAIT exists to replace.
|
|
spin:
|
|
; 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 spin
|
|
|
|
CALL newLine
|
|
RSTA
|
|
OUTA 0x02 ; Line mode and no interrupts, the way it was found.
|
|
SETD.0 DoneText
|
|
CALL printString
|
|
CALL newLine
|
|
RSTA
|
|
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
|