; Stopping a program to look at it. ; ; SWI osBreak shows every register as this program had them, waits for a key, and carries ; on. It is two bytes and it fires every time it is reached. ; ; WHY IT IS AN INSTRUCTION RATHER THAN SOMETHING SET FROM OUTSIDE. A breakpoint that was ; poked into a running program would have to overwrite an instruction, and then 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 one instruction. Nothing is overwritten here, ; so there is nothing to restore and nothing to re-arm. ; ; The price is that it is part of the program. A build with breakpoints in it has different ; addresses from a build without, which is the same bargain every machine makes that has a ; break instruction. ; ; 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. ; ; EVERY POINTER IS SET BEFORE EACH STOP, and the three this program owns are rotated ; between the two so that all of them visibly change. ; ; This program used to leave DP1 and DP2 alone, and what a stop then showed for them was ; whatever the shell happened to have left there. That is a real thing about the machine - ; a program is handed the pointers as it finds them - but it is not this program's to ; demonstrate, and it made what this program prints depend on where CosmOS's code happens ; to sit. The recorded output had to be taken again four times in one day's work, every ; time for a value nothing should ever depend on. ; ; A demonstration of what the registers were should show registers somebody chose. Then ; every line of it is being asserted rather than merely observed. ; ; DP3 is deliberately still the system's. It is where the program was entered, which is the ; one thing here worth seeing that this program did not choose, and it is steady because it ; is this program's own base. #Include services.asm #Program #Base 0x4000 start: SETD.0 Banner SWI osPrintString INIA 0d17 INIB 0d34 SETD.0 Marker SETD.1 Banner SETD.2 DoneText 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 RSTA SWI osExit deeper: INIA 0d68 INIB 0d85 SETD.0 Banner SETD.1 DoneText SETD.2 Marker SWI osBreak RET #Data #Base 0x2000 Banner: "two stops, and what the registers were at each " Marker: "marker" DoneText: "carried on to the end "