Breakpoints: SWI osBreak, and s refuses a read only bank

A breakpoint that shows every register as the program had them, waits for a
key, and carries on.

NOTHING IS OVERWRITTEN, and that is the design rather than a shortcut. A
breakpoint poked into a running program has to replace an instruction, and
putting that instruction back in order to continue is the same act as
disarming the breakpoint; firing a second time would mean stepping over the
restored instruction and putting the breakpoint back behind it, and this
machine cannot step a single instruction. SWI is two bytes, dispatches
through a vector, and its frame already holds the address after it, so RETI
resumes at the next instruction with nothing to restore and nothing to
re-arm. It fires every time it is reached.

The price is that a breakpoint is part of the program: a build with them in
has different addresses from a build without. That is the bargain every
machine with a break instruction makes.

Every value shown comes out of the frame rather than the registers, because
by the time the handler runs the registers are the handler's. Apps/Break.asm
stops twice so that the second stop is checked as well as the first.

Also here, found by the test that came with it: the monitor's s wrote into
whichever bank was selected, and bank 2 is the controller's own table,
published read only. Writing to it was refused, and a refusal nobody catches
stops the machine - so selecting the bank table to look at it and then typing
s killed the session. bankPresent now keeps the whole flags byte and s
declines. The recorded output of cosmosMonitor had contained that crash,
having been blessed without being read.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Anachronaut
2026-08-19 22:09:21 -04:00
co-authored by Claude Opus 5
parent b36d438132
commit 5fd995aa62
11 changed files with 326 additions and 3 deletions
+16
View File
@@ -0,0 +1,16 @@
CosmOS
> loaded, starting at 2000
> two stops, and what the registers were at each
break at 200E
A 11 B 22 Q 00 S 00
DP0 1030 DP1 05CC DP2 039A DP3 2000
press a key
break at 2018
A 44 B 55 Q 00 S 00
DP0 1000 DP1 05CC DP2 039A DP3 2000
press a key
carried on to the end
finished
> halted
Execution halted.
[exit 0]
+31 -2
View File
@@ -26,6 +26,35 @@ CosmOS
0010 03 FF 08 00 00 00 00 00 01 20 01 00 00 00 00 00 ......... ......
0020 00 FF 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 ................
0030 00 FF 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 ................
* Fault: The device on port 233 refused the access at Program Address 0x1359, and nothing is installed to deal with it.
* that bank will not be written
* bank 00
* * 8000 26 48 INIA 48
8002 D1 00 OUTA 00
8004 26 0A INIA 0A
8006 D1 00 OUTA 00
8008 18 12 SWI 12
800A 00 ADD
800B 00 ADD
800C 00 ADD
* H
finished
* 8000 26 48 INIA 48
8002 D1 00 OUTA 00
8004 26 0A INIA 0A
8006 D1 00 OUTA 00
8008 18 12 SWI 12
800A 00 ADD
800B 00 ADD
800C 00 ADD
* > greet.sbx 210
hello.sbx 52
Life.sbx 1411
Snake.sbx 2175
Keys.sbx 663
Say.sbx 155
Break.sbx 128
notes.txt 21
8 files
> halted
Execution halted.
[exit 1]
[exit 0]
+2 -1
View File
@@ -6,8 +6,9 @@ Life.sbx 1411
Snake.sbx 2175
Keys.sbx 663
Say.sbx 155
Break.sbx 128
notes.txt 21
7 files
8 files
> load what?
> no such file
> not a program
+5
View File
@@ -0,0 +1,5 @@
load Break.sbx
run
exit
+2
View File
@@ -9,6 +9,8 @@ b data
x 1000
b 2
x 0
s 0 FF
b program
s 8000 26 48 D1 00 26 0A D1 00 18 12
d 8000
g 8000
+5
View File
@@ -91,6 +91,11 @@ for i in 1 2 3 4 5 6 7 8; do "$TOOL" put "$DISKS/sbfs.img" "filler$i.txt" >/dev/
"$ROOT/Assembler" -I "$ROOT/Programs/CosmOS/Source" \
"$ROOT/Programs/CosmOS/Apps/Say.asm" -o "$WORK/Say.sbx" >/dev/null
"$TOOL" put "$DISKS/cosmos.img" "$WORK/Say.sbx" >/dev/null
# Break.sbx stops itself twice and shows what the registers were each time. It needs no disk
# of its own: it only prints.
"$ROOT/Assembler" -I "$ROOT/Programs/CosmOS/Source" \
"$ROOT/Programs/CosmOS/Apps/Break.asm" -o "$WORK/Break.sbx" >/dev/null
"$TOOL" put "$DISKS/cosmos.img" "$WORK/Break.sbx" >/dev/null
printf 'this is not a program' > notes.txt
"$TOOL" put "$DISKS/cosmos.img" notes.txt >/dev/null
+12
View File
@@ -221,6 +221,10 @@ cosmosRun | CosmOS/Source/cosmos.asm | run | cosmosRun
# The last part is what the mode is FOR: a program typed in as bytes, run with g, and the
# prompt that comes back is the monitor's own. A program giving the machine back lands where
# it was started from, so looking at something and running it do not interrupt each other.
#
# It also asks to write into bank 2, the controller's own table, which is published read
# only. That used to stop the machine, and the recorded output of this test contained the
# crash without anybody noticing, which is what blessing a result without reading it buys.
cosmosMonitor | CosmOS/Source/cosmos.asm | run | cosmosMonitor.in | - | disks/cosmos.img
# The original hello.asm, brought over as an application. It is not much of a program,
# but it is the one that talks to the hardware directly: it writes to port 0x00 instead
@@ -270,6 +274,13 @@ cosmosFiles | CosmOS/Source/cosmos.asm | run | cosmosFil
# name, and with several words, since what arrives is the rest of the line rather than a
# list and it is the program's business what to make of it.
cosmosSay | CosmOS/Source/cosmos.asm | run | cosmosSay.in | - | disks/cosmos.img
# A program stopping itself to be looked at. Two breakpoints, so what is checked is not only
# that one fires but that the SECOND one does - which is the whole difference between this
# design and one that overwrites an instruction, since an overwritten instruction has to be
# put back to continue and putting it back is the same act as disarming the breakpoint.
# Every value shown comes out of the interrupt frame rather than the registers, because by
# the time the handler runs the registers are the handler's.
cosmosBreak | CosmOS/Source/cosmos.asm | run | cosmosBreak.in | - | disks/cosmos.img
# The editor, which is the first program on this machine that makes a file a person typed:
# every byte on every other image here was put there by the host tool. It is run twice in
# one session, and that is the test rather than a flourish - the second run reads back what
@@ -291,6 +302,7 @@ app-Life | CosmOS/Apps/Life.asm | assemble | -
app-Snake | CosmOS/Apps/Snake.asm | assemble | - | -
app-Keys | CosmOS/Apps/Keys.asm | assemble | - | -
app-Say | CosmOS/Apps/Say.asm | assemble | - | -
app-Break | CosmOS/Apps/Break.asm | assemble | - | -
app-Edit | CosmOS/Apps/Edit.asm | assemble | - | -
app-Files | CosmOS/Apps/Files.asm | assemble | - | -