Break: name the status register properly and show the Stack Pointer
The dump labelled the status register "S", which reads as Stack to anybody sensible - and the Stack Pointer was the one register it did not show, so there was nothing to contradict the guess. It is written "status" now, and followed by the bits that are up, because a dump that makes you look the number up is only half a dump. The Stack Pointer is not in the frame, since the frame is where the Stack Pointer is. What the program had is fourteen bytes above it, that being what entering an interrupt puts down, so it is worked out and shown. Apps/Break.asm takes its second stop inside a subroutine, so the recorded output shows the Stack Pointer at FFFF and then at FFF5: a difference of ten, which is the size of a CALL frame. That checks the value is derived rather than constant, which the previous version could not have told you. Reported by Anachronaut, who read the output and asked why a pointer was two digits long. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
5fd995aa62
commit
c23adb2836
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user