A program can say how it went
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.
This commit is contained in:
@@ -58,6 +58,7 @@ start:
|
||||
|
||||
SETD.0 DoneText
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
deeper:
|
||||
|
||||
@@ -47,6 +47,7 @@ start:
|
||||
BNQ refused
|
||||
SETD.0 Allowed
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
refused:
|
||||
@@ -60,19 +61,23 @@ refused:
|
||||
BNQ noHonest
|
||||
SETD.0 Honest
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
noHonest:
|
||||
SETD.0 NoHonest
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
noStart:
|
||||
SETD.0 NoStart
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
noWrite:
|
||||
SETD.0 NoWrite
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -202,30 +202,37 @@ byteBorrow:
|
||||
alike:
|
||||
SETD.0 SameText
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
different:
|
||||
SETD.0 DifferentText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
usage:
|
||||
SETD.0 Usage
|
||||
SWI osPrintString
|
||||
INIA 0d2
|
||||
SWI osExit
|
||||
firstFailed:
|
||||
SETD.0 FirstError
|
||||
SWI osPrintString
|
||||
INIA 0d2
|
||||
SWI osExit
|
||||
secondFailed:
|
||||
SETD.0 SecondError
|
||||
SWI osPrintString
|
||||
INIA 0d2
|
||||
SWI osExit
|
||||
firstReadFailed:
|
||||
SETD.0 FirstReadError
|
||||
SWI osPrintString
|
||||
INIA 0d2
|
||||
SWI osExit
|
||||
secondReadFailed:
|
||||
SETD.0 SecondReadError
|
||||
SWI osPrintString
|
||||
INIA 0d2
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -154,6 +154,7 @@ copyDone:
|
||||
BNQ doneFailed
|
||||
SETD.0 Copied
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
; DP0 names the source word and DP1 the destination word.
|
||||
@@ -202,26 +203,32 @@ takeBorrow:
|
||||
usage:
|
||||
SETD.0 Usage
|
||||
SWI osPrintString
|
||||
INIA 0d2
|
||||
SWI osExit
|
||||
sourceFailed:
|
||||
SETD.0 SourceError
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
readFailed:
|
||||
SETD.0 ReadError
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
startFailed:
|
||||
SETD.0 StartError
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
writeFailed:
|
||||
SETD.0 WriteError
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
doneFailed:
|
||||
SETD.0 DoneError
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -161,12 +161,14 @@ commandArgument:
|
||||
BRI commandLoop
|
||||
|
||||
quit:
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
noName:
|
||||
SETD.0 NoNameText
|
||||
SWI osPrintString
|
||||
CALL newLine
|
||||
INIA 0d2
|
||||
SWI osExit
|
||||
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ start:
|
||||
BRI start
|
||||
end:
|
||||
CALL lineFeed
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -123,6 +123,7 @@ start:
|
||||
end:
|
||||
CALL lineFeed
|
||||
;HALT
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -33,6 +33,7 @@ start:
|
||||
end:
|
||||
CALL lineFeed
|
||||
;HALT
|
||||
RSTA
|
||||
SWI osExit ; Return to CosmOS.
|
||||
|
||||
#Data
|
||||
|
||||
@@ -101,28 +101,34 @@ atEnd:
|
||||
BRQ stillThere
|
||||
SETD.0 GoneText
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
stillThere:
|
||||
SETD.0 StillText
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
noSave:
|
||||
SETD.0 NoSaveText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
noRead:
|
||||
SETD.0 NoReadText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
noRename:
|
||||
SETD.0 NoRenameText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
noDelete:
|
||||
SETD.0 NoDeleteText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -56,6 +56,7 @@ spin:
|
||||
SETD.0 DoneText
|
||||
CALL printString
|
||||
CALL newLine
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
; Entered because the console had something to say. Never called.
|
||||
|
||||
@@ -105,6 +105,7 @@ lifeEnd:
|
||||
CALL lineFeed
|
||||
CALL printString ; DP0 still holds the words: CALL puts DP0 back.
|
||||
CALL lineFeed
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
seedGlider:
|
||||
|
||||
@@ -109,6 +109,7 @@ fullPage:
|
||||
noName:
|
||||
SETD.0 Usage
|
||||
SWI osPrintString
|
||||
INIA 0d2
|
||||
SWI osExit
|
||||
openFailed:
|
||||
SETD.0 OpenError
|
||||
@@ -123,7 +124,14 @@ printError:
|
||||
SWI osPrintNumber
|
||||
SETD.0 NewLine
|
||||
SWI osPrintString
|
||||
; ITS OWN EXIT, and it did not have one. This fell through into finished and reported
|
||||
; that everything was fine, having just printed the reason it was not - which nobody
|
||||
; noticed while the only reader was a person, who could see both.
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
finished:
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -118,6 +118,7 @@ theTail:
|
||||
SWI osPrintNumber
|
||||
SETD.0 AndTail
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
; The block becomes 256 copies of the block number plus a fixed byte, so that a block
|
||||
@@ -198,14 +199,17 @@ tenLoop:
|
||||
startFailed:
|
||||
SETD.0 NoStart
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
writeFailed:
|
||||
SETD.0 NoWrite
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
doneFailed:
|
||||
SETD.0 NoDone
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -40,6 +40,7 @@ sayNothing:
|
||||
sayEnd:
|
||||
SETD.0 NewLine
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -54,16 +54,19 @@ doSettle:
|
||||
BNA settleFailed
|
||||
SETD.0 Settled
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
settleFailed:
|
||||
SETD.0 NoDisk
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
alreadySettled:
|
||||
SETD.0 Already
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -74,6 +74,7 @@ advancePage:
|
||||
|
||||
finished:
|
||||
CALL lineFeed
|
||||
RSTA
|
||||
SWI osExit ; Return to CosmOS.
|
||||
|
||||
; DP0 points at a PrimeStates entry. CALL restores it on return.
|
||||
|
||||
@@ -38,6 +38,7 @@ start:
|
||||
BRI markMultiples ; Otherwise, loop again to mark the next multiple as nonprime.
|
||||
end:
|
||||
CALL lineFeed ; Print a linefeed to make it look nice.
|
||||
RSTA
|
||||
SWI osExit ; The program is done, we found all the primes!
|
||||
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ gameOverSay:
|
||||
CALL newLine
|
||||
RSTA
|
||||
OUTA 0x02 ; Line mode, the way it was found.
|
||||
RSTA ; splitlint[redundant-assignment]: an exit status, not a console mode
|
||||
SWI osExit
|
||||
|
||||
; ---- Reaching a square ----
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
; Status.asm
|
||||
; Says what the last program made of what it was asked to do.
|
||||
;
|
||||
; The shell keeps the number and does not print it, because a program that failed has
|
||||
; already said so in words and a number beside that would be noise. But a number nobody can
|
||||
; see is a number nobody can trust, so this is how a person looks.
|
||||
;
|
||||
; 0 it did what it was asked
|
||||
; 1 it did not
|
||||
; 2 it was asked wrongly
|
||||
;
|
||||
; A program may give its own meanings if it says so, and Compare does: one there means the
|
||||
; files differ, which is a result rather than a failure.
|
||||
;
|
||||
; Written by Anachronaut
|
||||
|
||||
#Include services.asm
|
||||
|
||||
#Program
|
||||
|
||||
#Base 0x4000
|
||||
|
||||
start:
|
||||
SWI osLastStatus
|
||||
MVQA
|
||||
SETD.0 Was
|
||||
STA.0
|
||||
|
||||
SETD.0 Prefix
|
||||
SWI osPrintString
|
||||
|
||||
; A and B together, most significant first - so the status is the LOW half. Put in A the
|
||||
; first time this was written, which printed a status of two as five hundred and twelve.
|
||||
RSTA
|
||||
SETD.0 Was
|
||||
LDB.0
|
||||
SWI osPrintNumber
|
||||
|
||||
; And in words, for the three the system itself uses.
|
||||
SETD.0 Was
|
||||
LDA.0
|
||||
BRA sayWorked
|
||||
INIB 0d1
|
||||
XOR
|
||||
BRQ sayFailed
|
||||
SETD.0 Was
|
||||
LDA.0
|
||||
INIB 0d2
|
||||
XOR
|
||||
BRQ sayAsked
|
||||
BRI done
|
||||
|
||||
sayWorked:
|
||||
SETD.0 WorkedText
|
||||
SWI osPrintString
|
||||
BRI done
|
||||
sayFailed:
|
||||
SETD.0 FailedText
|
||||
SWI osPrintString
|
||||
BRI done
|
||||
sayAsked:
|
||||
SETD.0 AskedText
|
||||
SWI osPrintString
|
||||
|
||||
done:
|
||||
SETD.0 NewLine
|
||||
SWI osPrintString
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
#Base 0x2000
|
||||
|
||||
Prefix:
|
||||
"the last program left "
|
||||
WorkedText:
|
||||
", which is: it did what it was asked"
|
||||
FailedText:
|
||||
", which is: it did not"
|
||||
AskedText:
|
||||
", which is: it was asked wrongly"
|
||||
NewLine:
|
||||
"
|
||||
"
|
||||
Was:
|
||||
0x00
|
||||
@@ -216,6 +216,7 @@ missing:
|
||||
SWI osPrintString
|
||||
CALL printWhy
|
||||
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
noBig:
|
||||
@@ -223,14 +224,17 @@ noBig:
|
||||
SETD.0 NoBigText
|
||||
SWI osPrintString
|
||||
CALL printWhy
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
noSmall:
|
||||
SETD.0 NoSmallText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
noRename:
|
||||
SETD.0 NoRenameText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
; ---- Routines ----
|
||||
|
||||
@@ -44,6 +44,7 @@ printLoop:
|
||||
noName:
|
||||
SETD.0 Usage
|
||||
SWI osPrintString
|
||||
INIA 0d2
|
||||
SWI osExit
|
||||
openFailed:
|
||||
SETD.0 OpenError
|
||||
@@ -58,7 +59,14 @@ printError:
|
||||
SWI osPrintNumber
|
||||
SETD.0 NewLine
|
||||
SWI osPrintString
|
||||
; ITS OWN EXIT, and it did not have one. This fell through into finished and reported
|
||||
; that everything was fine, having just printed the reason it was not - which nobody
|
||||
; noticed while the only reader was a person, who could see both.
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
finished:
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -65,19 +65,23 @@ wanderByte:
|
||||
BRI wanderBlock
|
||||
|
||||
wanderDone:
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
noWhere:
|
||||
SETD.0 NoWhereText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
noSuchPlace:
|
||||
SETD.0 NoPlaceText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
noFile:
|
||||
SETD.0 NoFileText
|
||||
SWI osPrintString
|
||||
INIA 0d1
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -39,6 +39,7 @@ greet:
|
||||
|
||||
; Give the machine back. The system takes its Stack back at this point, so everything
|
||||
; this program pushed goes with it.
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
@@ -21,6 +21,7 @@ End:
|
||||
OUTA 0x00 ; Output it to the text console.
|
||||
;HALT ; Terminate the program.
|
||||
; Instead, let's call osExit to return the system nicely. Fourth change.
|
||||
RSTA
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
|
||||
+28
-25
@@ -361,8 +361,9 @@ from every assembly file in it. Several are old programs written for the bare ma
|
||||
| Snake | A game. Draws a whole screen with cursor addressing and steers with single keys, asking the console once a frame and never waiting. |
|
||||
| Keys | The console interrupting rather than being asked. The only one that brings a vector of its own, which is what the version two format exists for. |
|
||||
| Say | Prints whatever it was told, which is the shortest thing that shows osArgument working. |
|
||||
| Settle | Says how the last start went and tells the machine to stop falling back, in 349 bytes. A program rather than a shell word, because the shell is for what cannot be done without it. |
|
||||
| Files | Writes a file, reads it back, renames it and deletes it, in 665 bytes, including nothing but the service names. It is what says a program does not need a filesystem inside it. |
|
||||
| Status | Says what the last program made of what it was asked to do, in 222 bytes. The shell keeps the number and does not print it; this is how a person looks. |
|
||||
| Settle | Says how the last start went and tells the machine to stop falling back, in 353 bytes. A program rather than a shell word, because the shell is for what cannot be done without it. |
|
||||
| Files | Writes a file, reads it back, renames it and deletes it, in 675 bytes, including nothing but the service names. It is what says a program does not need a filesystem inside it. |
|
||||
| Break | Stops itself twice with SWI osBreak, so that the registers can be seen changing between one stop and the next. |
|
||||
| Edit | A line editor. |
|
||||
| Stream | Reads an 84,000 byte file through a buffer of 256, which is what says a file bigger than Data Memory can be read at all. |
|
||||
@@ -463,7 +464,7 @@ Typed in as bytes, checked by disassembling it back, and run. It ends with `SWI
|
||||
|
||||
`Edit` is the first program on this machine that makes a file a person typed - every byte on every disk before it was put there by the host tool. It is line oriented in the manner of `ed`: `l` lists, `a` adds at the end, `i` and `c` and `d` take a line number, `w` writes and `q` stops.
|
||||
|
||||
It includes nothing but `services.asm` and `text.asm`: the filesystem and the console are the system's, asked for rather than carried. That is what brought `Edit` down from 4,941 bytes to 1,983 bytes without a line of its own logic changing - and the way that was checked is worth knowing, because the recorded output of the `cosmosEdit` test did not move by a single byte across the rewrite.
|
||||
It includes nothing but `services.asm` and `text.asm`: the filesystem and the console are the system's, asked for rather than carried. That is what brought `Edit` down from 4,941 bytes to 1,986 bytes without a line of its own logic changing - and the way that was checked is worth knowing, because the recorded output of the `cosmosEdit` test did not move by a single byte across the rewrite.
|
||||
|
||||
It keeps the document as a **linked list of lines** rather than one buffer with newlines in it. Each line says where the next one is, how long it is, and then its bytes. Inserting is two pointers changed and nothing moved; with a flat buffer it would mean shifting every byte after the edit, on a machine whose only block move is a device asked politely. The price is that deleted lines are not reused, so a heavy session uses more room than the document needs and writing it out is what tidies up.
|
||||
|
||||
@@ -591,6 +592,7 @@ Those numbers are written down once, in `Programs/CosmOS/Source/services.asm`, w
|
||||
| osFileFetch | DP1 is where a block should go, A and B together are which block. Reads back a block of the file being written. |
|
||||
| osPrintNumber | A and B together are a number. Prints it in decimal, without leading zeroes. |
|
||||
| osBreak | Stops the program, shows every register as it had them, waits for a key, and carries on. |
|
||||
| osLastStatus | Q answers what the last program exited with: 0 it did what it was asked, 1 it did not, 2 it was asked wrongly. A program may give its own meanings if it says so. |
|
||||
| osBootState | Q answers how the last start went: 0 settled, 1 trying, 2 fell back. A machine with no disk answers settled, because there is nothing there to be unsettled about. |
|
||||
| osBootSettle | Puts it back to settled, which is how a machine that fell back is told the situation has changed. Q is zero if the disk took it. **Settling is the only write a program gets** - marking a start as trying or fallen back is the loader's business, and a service that let a program claim either would let it lie about something the loader cannot check. |
|
||||
|
||||
@@ -675,33 +677,12 @@ Running off the end is how a reader finds out it has finished, so it gets an ans
|
||||
|
||||
`Programs/CosmOS/Apps/Stream.asm` reads an 84,000 byte file through a 256 byte buffer, then reads a small file both ways - whole with `osFileRead` and streamed - and checks that the two agree.
|
||||
|
||||
`Programs/CosmOS/Apps/Files.asm` does the whole round trip - write, read, report, rename, delete - in 665 bytes, and includes nothing but the service names.
|
||||
`Programs/CosmOS/Apps/Files.asm` does the whole round trip - write, read, report, rename, delete - in 675 bytes, and includes nothing but the service names.
|
||||
|
||||
`osArgument` is how a program is told what it is for. Everything written before it did the same thing however it was started, which is fine for a program that greets you and no use to one that edits a named document. What arrives is the whole rest of the line, spaces and all, rather than a list of words: what counts as an argument is the program's business, and handing over what was typed is the system's.
|
||||
|
||||
A handler is entered with the caller's registers exactly as they were, because an interrupt frame is pushed rather than cleared. That is why a service can be given a pointer in DP0 and a count in B without any of it being copied anywhere first.
|
||||
|
||||
### How A Service Answers:
|
||||
|
||||
The same thing that makes an interrupt safe makes a service mute. RETI restores every register from the frame, so whatever a handler worked out is thrown away on the way out - which is exactly right for a device interrupting at a moment nobody chose, and useless for a service that was asked a question.
|
||||
|
||||
A service answers by **writing into its own frame**, over the saved register, and letting RETI put it back. MVSD copies the Stack Pointer into a Data Pointer and the frame sits just above it, so returning a byte in Q is three instructions:
|
||||
|
||||
```
|
||||
answer:
|
||||
INIA 0d42
|
||||
MVSD.1
|
||||
DPUP.1 0d02 ; The saved Q. See the frame table under Interrupts.
|
||||
STA.1
|
||||
RETI
|
||||
```
|
||||
|
||||
**Which registers a service may answer in is the convention CALL already has: Q and DP3.** A subroutine cannot hand back A, B or Data Pointers 0 to 2 because RET puts them back; a service *could* write over any of them and should not, for exactly the reason that list exists. A caller is entitled to find what it kept still there.
|
||||
|
||||
**Only the handler itself can do this.** The offsets are from wherever the Stack Pointer is, and a CALL moves it by ten - so a routine called by a handler that tried the same thing would be writing into its own return address. The poke belongs inline, next to the RETI.
|
||||
|
||||
A service that has nothing to say does nothing, and the caller's registers arrive back untouched. That is worth knowing from the other side too: a service cannot corrupt a register by accident, only by deciding to.
|
||||
|
||||
## The Filesystem Library:
|
||||
|
||||
The disk knows blocks and nothing else, so a filesystem is software. Programs/CosmOS/Source/sbfs.asm is one.
|
||||
@@ -884,6 +865,28 @@ A file's length is its block count times 256 plus its tail, which is the same as
|
||||
|
||||
The other implementation of this format is SplitDisk, on the host. Nothing is shared between the two but the specification, so a change to either has to be a change to both.
|
||||
|
||||
### What A Program Made Of It:
|
||||
|
||||
`SWI osExit` takes a status **in A**: zero if the program did what it was asked, one if it
|
||||
did not, two if it was asked wrongly. A program may give its own meanings if it says so, and
|
||||
`Compare` does - one there means the files differ, which is a result rather than a failure.
|
||||
|
||||
**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 setting it to a small number costs four instructions where A costs one.
|
||||
|
||||
**The shell keeps the number and does not print it.** A program that failed has already said
|
||||
so in words, and a number beside that would be noise. `osLastStatus` hands it back and
|
||||
`Status` is the program that shows it. The indirection is the point: this number is for the
|
||||
thing that cannot read words - whatever comes to run programs in sequence and has to decide
|
||||
whether to run the next one.
|
||||
|
||||
Marking all fifty eight exits found a defect on its 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.
|
||||
|
||||
### How A Service Answers:
|
||||
|
||||
A handler arrives with the caller's registers pushed rather than cleared, and **`RETI`
|
||||
|
||||
@@ -2242,6 +2242,18 @@ handlePrintNumber:
|
||||
;
|
||||
; Which is exactly why this cannot RETI. Its return address is on the Stack it just walked
|
||||
; away from, so it branches to the prompt instead.
|
||||
; What the last program made of what it was asked to do. Kept rather than shown: a program
|
||||
; that failed has already said so in words, and a number beside that would be noise. It is
|
||||
; here for the thing that cannot read words - whatever comes to run programs in sequence and
|
||||
; has to decide whether to run the next one.
|
||||
handleLastStatus:
|
||||
SETD.2 LastStatus
|
||||
LDA.2
|
||||
RSTB
|
||||
CCF
|
||||
ADD ; A is the answer, so Q becomes it.
|
||||
SRET
|
||||
|
||||
; ---- How the last start went, and settling it ----
|
||||
;
|
||||
; The answer goes in Q by writing into this handler's own frame, which is how every service
|
||||
@@ -2292,6 +2304,17 @@ bootSettleNo:
|
||||
SRET
|
||||
|
||||
handleExit:
|
||||
; ---- What the program made of it ----
|
||||
;
|
||||
; A, before anything below disturbs it. IN A RATHER THAN Q, and that 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. The register a
|
||||
; subroutine cannot hand anything back in is exactly the one that is free here - and Q is
|
||||
; the ALU's output, so setting it to a small number costs four instructions where A costs
|
||||
; one.
|
||||
SETD.1 LastStatus
|
||||
STA.1
|
||||
|
||||
SETD.1 SystemStack
|
||||
LDD.0.1
|
||||
MVDS.0
|
||||
@@ -3417,6 +3440,10 @@ Banner:
|
||||
"CosmOS"
|
||||
PromptText:
|
||||
"> "
|
||||
; Nothing has run yet, so nothing has failed yet.
|
||||
LastStatus:
|
||||
0x00
|
||||
|
||||
OnFallback:
|
||||
"this is the fallback: what boot.cfg asks for did not start
|
||||
"
|
||||
@@ -3913,6 +3940,7 @@ CommandLine:
|
||||
osFileFetch handleFileFetch
|
||||
osPrintNumber handlePrintNumber
|
||||
osBreak handleBreak
|
||||
osLastStatus handleLastStatus
|
||||
osBootState handleBootState
|
||||
osBootSettle handleBootSettle
|
||||
Device 0x20 diskDone
|
||||
|
||||
@@ -153,3 +153,17 @@
|
||||
; about something the loader has no way to check.
|
||||
osBootState 0d33
|
||||
osBootSettle 0d34
|
||||
|
||||
; ---- What a program made of it ----
|
||||
;
|
||||
; osExit takes a status in A: zero if the program did what it was asked, and a number of
|
||||
; its own choosing if it did not. 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
|
||||
; does, and 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 and one in A.
|
||||
;
|
||||
; osLastStatus answers in Q with what the last program exited with. The shell does not
|
||||
; print it: a program that failed has already said so in words, and a number beside that
|
||||
; would be noise. This is for the thing that cannot read words.
|
||||
osLastStatus 0d35
|
||||
|
||||
Reference in New Issue
Block a user