The shell starts each line with the Stack where it left it
Every failure in this shell abandons a frame. commandFailed is reached with CALL and never returns: it marks the line and branches to the prompt, which is the idiom every command uses and is why a failure needs no unwinding anywhere. What it costs is the frame of that call and of everything between the prompt and it - twenty bytes for a name that was never set, more from somewhere deeper - and nothing ever gave them back. MEASURED BEFORE IT WAS FIXED. Twenty failed lines moved the Stack Pointer from FFFD to FE6D, and it only ever went one way. Nothing had noticed because it takes thousands of failures to reach anything and nobody types thousands of anything. A loop in a script would, which is why this is worth doing before there are loops rather than after. So the loop starts each turn from a known place. SystemStack is NOT that place: it is taken when a program starts, so that the shell's Stack can be given back when the program stops - which means it holds wherever the shell had got to at that moment, the value that needs correcting rather than the one to correct from. ShellStack is taken once, at boot, when nothing is happening. Second use of MVDS in the system, and it earns it for the same reason as the first: a Stack that is right by construction beats one that is right because everybody remembered. Break prints the registers, so the test is two dumps with eight failures between them and a requirement that they agree. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
a8707f29f0
commit
4b109f704c
@@ -146,6 +146,16 @@ bootStartup:
|
|||||||
CALL newLine
|
CALL newLine
|
||||||
bootReady:
|
bootReady:
|
||||||
|
|
||||||
|
; ---- Where the Stack is when nothing is happening ----
|
||||||
|
;
|
||||||
|
; Taken once, here, and put back at the top of every turn of the loop below. SystemStack is
|
||||||
|
; not this: that is taken when a PROGRAM starts, to be given back when it stops, so it
|
||||||
|
; holds wherever the shell had got to at that moment - which is the value that needs
|
||||||
|
; correcting rather than the one to correct from.
|
||||||
|
MVSD.0
|
||||||
|
SETD.1 ShellStack
|
||||||
|
STD.0.1
|
||||||
|
|
||||||
; ---- The loop ----
|
; ---- The loop ----
|
||||||
;
|
;
|
||||||
; The shell has two modes and one prompt that says which. Ordinary mode runs programs;
|
; The shell has two modes and one prompt that says which. Ordinary mode runs programs;
|
||||||
@@ -158,6 +168,25 @@ bootReady:
|
|||||||
; shell. Only saying so leaves the monitor, or a program breaking the machine badly enough
|
; shell. Only saying so leaves the monitor, or a program breaking the machine badly enough
|
||||||
; to need starting again.
|
; to need starting again.
|
||||||
prompt:
|
prompt:
|
||||||
|
; ---- The Stack, back where it was when nothing was happening ----
|
||||||
|
;
|
||||||
|
; EVERY FAILURE IN THIS SHELL ABANDONS A FRAME. commandFailed is reached with CALL and
|
||||||
|
; never returns: it marks the line and branches here, which is the idiom every command
|
||||||
|
; uses and is why a failure needs no unwinding. What it costs is the frame of that call and
|
||||||
|
; of everything between here and it - twenty bytes for a name that was never set, more from
|
||||||
|
; somewhere deeper - and nothing ever gave them back. Twenty failed lines moved the Stack
|
||||||
|
; Pointer from FFFD to FE6D, and it only ever went one way.
|
||||||
|
;
|
||||||
|
; Nothing had noticed because it takes thousands of failures to reach anything, and nobody
|
||||||
|
; types thousands of anything. A loop in a script would.
|
||||||
|
;
|
||||||
|
; So the loop starts each turn from a known place. This is the second use of MVDS in the
|
||||||
|
; system and it earns it for the same reason as the first: a Stack that is right by
|
||||||
|
; construction beats one that is right by everybody remembering.
|
||||||
|
SETD.1 ShellStack
|
||||||
|
LDD.0.1
|
||||||
|
MVDS.0
|
||||||
|
|
||||||
; ---- A script stops at the first line that did not work ----
|
; ---- A script stops at the first line that did not work ----
|
||||||
;
|
;
|
||||||
; Checked here, before the next line is read, because this is the one place every command
|
; Checked here, before the next line is read, because this is the one place every command
|
||||||
@@ -7226,6 +7255,9 @@ DumpBytes:
|
|||||||
; region a program owns, so that a program has to go looking to break it.
|
; region a program owns, so that a program has to go looking to break it.
|
||||||
SystemStack:
|
SystemStack:
|
||||||
0x00 0x00
|
0x00 0x00
|
||||||
|
; And where it is when the shell is between lines, which is not the same thing. See prompt.
|
||||||
|
ShellStack:
|
||||||
|
0x00 0x00
|
||||||
DirSeen:
|
DirSeen:
|
||||||
0x00
|
0x00
|
||||||
DirSize:
|
DirSize:
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ from `make`, not from here.
|
|||||||
### 1. Recorded output
|
### 1. Recorded output
|
||||||
|
|
||||||
`Tests/run.sh` assembles each program named in `Tests/manifest`, runs it, and compares
|
`Tests/run.sh` assembles each program named in `Tests/manifest`, runs it, and compares
|
||||||
everything it printed against a file in `Tests/expected`. 200 tests, of which 138 run, 35
|
everything it printed against a file in `Tests/expected`. 201 tests, of which 139 run, 35
|
||||||
only assemble, 16 are expected to fail to assemble, and 11 boot from ROM with no image
|
only assemble, 16 are expected to fail to assemble, and 11 boot from ROM with no image
|
||||||
given at all.
|
given at all.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
CosmOS
|
||||||
|
> Break
|
||||||
|
two stops, and what the registers were at each
|
||||||
|
break at 5016
|
||||||
|
A 11 B 22 Q 00 status 00
|
||||||
|
DP0 3030 DP1 3000 DP2 3037 DP3 5000 SP FFFF
|
||||||
|
press a key
|
||||||
|
break at 5034
|
||||||
|
A 44 B 55 Q 00 status 00
|
||||||
|
DP0 3000 DP1 3037 DP2 3030 DP3 5000 SP FFF5
|
||||||
|
press a key
|
||||||
|
carried on to the end
|
||||||
|
finished
|
||||||
|
> ho $nope
|
||||||
|
nothing is set called nope
|
||||||
|
> echo $nope
|
||||||
|
nothing is set called nope
|
||||||
|
> echo $nope
|
||||||
|
nothing is set called nope
|
||||||
|
> echo $nope
|
||||||
|
nothing is set called nope
|
||||||
|
> echo $nope
|
||||||
|
nothing is set called nope
|
||||||
|
> echo $nope
|
||||||
|
nothing is set called nope
|
||||||
|
> echo $nope
|
||||||
|
nothing is set called nope
|
||||||
|
> echo $nope
|
||||||
|
nothing is set called nope
|
||||||
|
> Break
|
||||||
|
two stops, and what the registers were at each
|
||||||
|
break at 5016
|
||||||
|
A 11 B 22 Q 00 status 00
|
||||||
|
DP0 3030 DP1 3000 DP2 3037 DP3 5000 SP FFFF
|
||||||
|
press a key
|
||||||
|
break at 5034
|
||||||
|
A 44 B 55 Q 00 status 00
|
||||||
|
DP0 3000 DP1 3037 DP2 3030 DP3 5000 SP FFF5
|
||||||
|
press a key
|
||||||
|
carried on to the end
|
||||||
|
finished
|
||||||
|
> it
|
||||||
|
I do not know: it
|
||||||
|
>
|
||||||
|
halted
|
||||||
|
Execution halted.
|
||||||
|
[exit 0]
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
Break
|
||||||
|
echo $nope
|
||||||
|
echo $nope
|
||||||
|
echo $nope
|
||||||
|
echo $nope
|
||||||
|
echo $nope
|
||||||
|
echo $nope
|
||||||
|
echo $nope
|
||||||
|
echo $nope
|
||||||
|
Break
|
||||||
|
exit
|
||||||
@@ -414,6 +414,17 @@ cosmosTabPath | CosmOS/Source/cosmos.asm | run | cosmosTab
|
|||||||
# refusing. Somebody who wants an empty value writes "set name" and gets one - the escape
|
# refusing. Somebody who wants an empty value writes "set name" and gets one - the escape
|
||||||
# hatch exists and has to be asked for.
|
# hatch exists and has to be asked for.
|
||||||
cosmosVars | CosmOS/Source/cosmos.asm | run | cosmosVars.in | - | disks/cosmos.img
|
cosmosVars | CosmOS/Source/cosmos.asm | run | cosmosVars.in | - | disks/cosmos.img
|
||||||
|
# The Stack is where it was, after eight lines that failed.
|
||||||
|
#
|
||||||
|
# EVERY FAILURE IN THIS SHELL ABANDONS A FRAME: commandFailed is reached with CALL and never
|
||||||
|
# returns, which is the idiom every command uses and is why a failure needs no unwinding.
|
||||||
|
# Nothing gave those frames back, so the Stack Pointer only ever moved one way - FFFD to FE6D
|
||||||
|
# over twenty failures. It took thousands to reach anything, which is why nobody had noticed;
|
||||||
|
# a loop in a script would have got there.
|
||||||
|
#
|
||||||
|
# Break is what makes it visible, because it prints the registers. The two dumps have to
|
||||||
|
# agree, and the failures between them are what would move it.
|
||||||
|
cosmosStack | CosmOS/Source/cosmos.asm | run | cosmosStack.in | - | disks/cosmos.img
|
||||||
# The same editing offered to a PROGRAM, through osReadLine. Edit reads its lines that way,
|
# The same editing offered to a PROGRAM, through osReadLine. Edit reads its lines that way,
|
||||||
# so a word typed with two letters the wrong way round is put right without starting the line
|
# so a word typed with two letters the wrong way round is put right without starting the line
|
||||||
# again - which is the whole of what A4 buys.
|
# again - which is the whole of what A4 buys.
|
||||||
|
|||||||
Reference in New Issue
Block a user