diff --git a/Programs/CosmOS/Apps/Break.asm b/Programs/CosmOS/Apps/Break.asm index 0876fa3..473aba6 100644 --- a/Programs/CosmOS/Apps/Break.asm +++ b/Programs/CosmOS/Apps/Break.asm @@ -14,8 +14,9 @@ ; addresses from a build without, which is the same bargain every machine makes that has a ; break instruction. ; -; Correct output is two stops, showing A and B changing between them, and the addresses of -; the two SWIs. +; Correct output is two stops. A and B differ between them, the addresses differ, and the +; Stack Pointer differs too, because the second one is inside a subroutine and a call has +; put ten bytes down by then. #Include services.asm @@ -32,16 +33,21 @@ start: SETD.0 Marker SWI osBreak - ; Something for the second stop to show as different. - INIA 0d68 - INIB 0d85 - SETD.0 Banner - SWI osBreak + ; The second stop is inside a subroutine, so that the Stack Pointer is visibly not where + ; it was: a call puts ten bytes down before this one gets there. + CALL deeper SETD.0 DoneText SWI osPrintString SWI osExit +deeper: + INIA 0d68 + INIB 0d85 + SETD.0 Banner + SWI osBreak + RET + #Data #Base 0x1000 diff --git a/Programs/CosmOS/Source/cosmos.asm b/Programs/CosmOS/Source/cosmos.asm index 79ff4e0..f6d286f 100644 --- a/Programs/CosmOS/Source/cosmos.asm +++ b/Programs/CosmOS/Source/cosmos.asm @@ -1049,6 +1049,35 @@ breakAddress: POPD.1 DPUP.1 0d1 CALL breakByte + + ; And which bits of it those are, since a debug dump that makes you look the number up is + ; only half of one. Halt is not among them: the machine is plainly not halted. + PSHD.3 + POPD.1 + DPUP.1 0d1 + LDA.1 + PSHA + INIB 0x01 + AND + BRQ breakNoCarry + SETD.0 CarryText + CALL printString +breakNoCarry: + POPA + PSHA + INIB 0x02 + AND + BRQ breakNoFault + SETD.0 FaultText + CALL printString +breakNoFault: + POPA + INIB 0x04 + AND + BRQ breakNoInts + SETD.0 IntsText + CALL printString +breakNoInts: CALL newLine SETD.0 DP0Text @@ -1071,6 +1100,22 @@ breakAddress: POPD.1 DPUP.1 0d5 CALL breakWord + + ; The Stack Pointer is not in the frame, because the frame is where the Stack Pointer is. + ; What the program had is fourteen bytes above this one, that being what entering an + ; interrupt puts down. + SETD.0 SPText + CALL printString + PSHD.3 + POPD.0 + DPUP.0 0d14 + PSHD.0 + POPB + POPA + CALL printByteHex + PSHB + POPA + CALL printByteHex CALL newLine ; Anything typed carries on. Reading the data port waits however the console is set, which @@ -1936,7 +1981,7 @@ BRegText: QRegText: "Q " SRegText: -"S " +"status " DP0Text: "DP0 " DP1Text: @@ -1945,6 +1990,14 @@ DP2Text: "DP2 " DP3Text: "DP3 " +SPText: +"SP " +CarryText: +"carry " +FaultText: +"fault " +IntsText: +"interrupts " ResumeText: "press a key " MonitorPrompt: diff --git a/SplitBit Programming Manual.md b/SplitBit Programming Manual.md index 34d1e63..e2c2565 100644 --- a/SplitBit Programming Manual.md +++ b/SplitBit Programming Manual.md @@ -575,13 +575,17 @@ Those numbers are written down once, in `Programs/CosmOS/Source/services.asm`, w ``` break at 200E -A 11 B 22 Q 00 S 00 -DP0 1030 DP1 05AE DP2 039A DP3 2000 +A 11 B 22 Q 00 status 00 +DP0 1030 DP1 05EF DP2 039A DP3 2000 SP FFFF press a key ``` Every value comes out of the interrupt frame rather than out of the registers, because by the time the handler runs the registers belong to the handler. The frame is what the program had and what RETI is about to give back, so what is shown is what will be resumed with. The address is two before where it resumes: the `SWI` and the vector it names. +**The Stack Pointer is the exception, because it is not in the frame** — the frame is *where* the Stack Pointer is. What the program had is fourteen bytes above the frame, that being what entering an interrupt puts down, so it is worked out rather than read. Breaking inside a subroutine shows it ten lower than breaking outside one, which is the size of a CALL frame and a quick way to see how deep you are. + +The status byte is shown as a number and then as the bits that are up — `carry`, `fault`, `interrupts` — because a dump that makes you look the number up is only half a dump. + **Nothing is overwritten, and that is the whole of why it is simple.** 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 has no way to step a single instruction. Two bytes of `SWI` cost a little space and fire for ever, because there was never anything to restore. The price is that a breakpoint is part of the program. A build with breakpoints in it has different addresses from a build without — the same bargain every machine makes that has a break instruction. diff --git a/Tests/expected/cosmosBreak.out b/Tests/expected/cosmosBreak.out index 28a8064..5a58477 100644 --- a/Tests/expected/cosmosBreak.out +++ b/Tests/expected/cosmosBreak.out @@ -2,12 +2,12 @@ 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 +A 11 B 22 Q 00 status 00 +DP0 1030 DP1 05EF DP2 039A DP3 2000 SP FFFF press a key -break at 2018 -A 44 B 55 Q 00 S 00 -DP0 1000 DP1 05CC DP2 039A DP3 2000 +break at 2023 +A 44 B 55 Q 00 status 00 +DP0 1000 DP1 05EF DP2 039A DP3 2000 SP FFF5 press a key carried on to the end finished diff --git a/Tests/expected/cosmosMonitor.out b/Tests/expected/cosmosMonitor.out index 8cd7812..610e898 100644 --- a/Tests/expected/cosmosMonitor.out +++ b/Tests/expected/cosmosMonitor.out @@ -52,7 +52,7 @@ Life.sbx 1411 Snake.sbx 2175 Keys.sbx 663 Say.sbx 155 -Break.sbx 128 +Break.sbx 132 notes.txt 21 8 files > halted diff --git a/Tests/expected/cosmosRun.out b/Tests/expected/cosmosRun.out index dc8a16c..4722a93 100644 --- a/Tests/expected/cosmosRun.out +++ b/Tests/expected/cosmosRun.out @@ -6,7 +6,7 @@ Life.sbx 1411 Snake.sbx 2175 Keys.sbx 663 Say.sbx 155 -Break.sbx 128 +Break.sbx 132 notes.txt 21 8 files > load what?