Info Jul 2016
Colin Ferris (399) 1814 posts |
Is there a proper way of stopping a program – ie : mov pc.#0 b 0 Swi OS_breakpt And being able to look at the Regs? How would the ‘High vector’ RO respond to the above? Would it be possible – for RO to use ‘High vectors or low’ depending on a CMOS value? Is there a module that accelerates the pointer across screen – that works with several versions of RO? |
Rick Murray (539) 13840 posts |
Can you be more specific? Do you want to stop it for good, or restart it, or what? The normal way to exit is to call OS_Exit. You could also return to the return address on the stack (if R14 was stacked at startup), but if you want to bomb out without knowing the state of the stack, OS_Exit is the way to go. I suppose you could claim a bit of memory in the RMA and dump the registers there prior to exiting, something like Branching to zero is, well, that’s the reset vector on low vector ARM – probably not what you would want to have happen. On a high vector ARM, I would imagine it would abort (I’m sitting outside in a deck chair – officially on holiday now) which as a side effect should dump the registers so that ShowRegs will display them…assuming RISC OS recovers by killing the application and doesn’t just stiff up. Do you have the DDE? If it is a regular task, DDT is awkward and annoying but it is quite good when it deems your project worthy enough that it will work. No, RISC OS cannot use CMOS to determine high or low vectors. That choice is not low level, that choice is bare metal. One needs to know where the vectors are before one can even think about reading CMOS. I do think, however, that the nightly builds ought to come in high and low vector flavours until we can be certain that bugs have been exorcised. |
Jon Abbott (1421) 2651 posts |
SWI OS_BreakPt will do what you require and if you want the breakpoint to call your own code, claim the Breakpoint Environment handler |
Rick Murray (539) 13840 posts |
Mmm, that’s simpler, yes. ;-) DDT is more flexible though. |
Colin Ferris (399) 1814 posts |
I’ve found a old module ‘BreakPt’ that does this and prints it to its own window. Think I have made it to work with RO 5.23 (25 Jul 16) – seemed to want to poke in a strange place in org vsn :-( Needs a little update to handle the flags properly. I would like to know – what params of below – should be:- r0=8 r1 = address of code r2=r12 r3 ??? SWI "XOS_ChangeEnvironment" r3 ??? and what should come out. Tks |
Jon Abbott (1421) 2651 posts |
R3 is a pointer to a word aligned, 16 word buffer for the register dump |
Colin Ferris (399) 1814 posts |
Tks – that is now 17 word buffer – extra word for the flags. swi OS_BreakPt is called. What does swi OS_Claim ,&1E – come into the sequence? Any simple examples – explaining RO vectors/events etc out there. |
Rick Murray (539) 13840 posts |
You mean the register order? I’d imagine R0-R15 then the CPSR.
Huh? If you use OS_BreakCtrl or OS_ChangeEnvironment, then your breakpoint handler will be called when OS_BreakPt happens. No before, no after, your handler is called in place of the default OS one.
Leave that alone. You can hook into the OS_ChangeEnvironment vector to modify behaviour (for example a debugger might want to trap your breakpoint handler and ensure its own is always in use). For using OS_BreakPt, you don’t need to touch this. I threw together a really basic example. [program code deleted, I’ve written something better] |
Rick Murray (539) 13840 posts |
I’ve removed all mention of “returning to the program” as it is NOT possible with that code as it stands. I went for a walk up the driveway and back (about a kilometre round trip) and I just couldn’t get around the fact that R14 is going to get trashed. The only way to avoid this is to run the entire breakpoint handler in SVC mode. |
Rick Murray (539) 13840 posts |
Okay, here’s code. First up, a simple little “wrapper”. This represents your program and indicates:
Here is the debug code. This handles setting up and removing the breakpoint handler, plus the handler itself. The handler runs in SVC mode and does some fiddling with USR mode while in SVC mode (hence why the LDM ^ and MOVS that are normally “not to be used” in 32 bit code). Edit: There’s a later better version on my website. Details further below…
Both programs use hardcoded SWI numbers so that they can be easily copied and built without need to special headers or anything. Just build the two files and link ’em together. ;-) Here is an example of the output: *BreakTest Breakpoint at &000080AC R0 = &00000000 (0) R1 = &00000011 (17) R2 = &00000022 (34) R3 = &00000033 (51) R4 = &00000044 (68) R5 = &00000055 (85) R6 = &00000066 (102) R7 = &00000077 (119) R8 = &0000000A (10) R9 = &30048584 (805602692) R10 = &FA208000 (4196433920) R11 = &FA207FA0 (4196433824) R12 = &80000000 (2147483648) R13 = &00408000 (4227072) R14 = &0000808C (32908) [C]ontinue or [Q]uit? Breakpoint at &000080B0 R0 = &00000000 (0) R1 = &00000011 (17) R2 = &00000022 (34) R3 = &00000033 (51) R4 = &00000044 (68) R5 = &00000055 (85) R6 = &00000066 (102) R7 = &00000077 (119) R8 = &0000000A (10) R9 = &30048584 (805602692) R10 = &FA208000 (4196433920) R11 = &FA207FA0 (4196433824) R12 = &80000000 (2147483648) R13 = &00408000 (4227072) R14 = &0000808C (32908) [C]ontinue or [Q]uit? Hasta la vista, BABY. * Have fun. (^_^) |
Colin Ferris (399) 1814 posts |
Thanks for your input – OS_BreakCtrl looks interesting. The placing of the Regs at a low value – &AE8 – where does this go in Hi vector RO? Two progs -one to set the Regs to a value. BASIC Progs END CALL go |
Steve Drain (222) 1620 posts |
I may be missing the point, and Martin Avison may be away, but isn’t this just what Reporter does? The simplest is just to include |
Rick Murray (539) 13840 posts |
Probably the same offset from whereever the high vector stuff begins. That said, it does not matter. The SWI exists to provide the information so you don’t make assumptions about where things go. The OS is free to put the register dump in other arbitrary places (RMA, for instance).
Hmm, not quite what OS_BreakPt is there for. ;-) |
Colin Ferris (399) 1814 posts |
Steve – Tend to use Report_Regs – shifting the higher regs – to within range if it is safe to – also seems to work ok in SVC. With BreakPt module – it seems to be poking (plus)+4 to the pc address – &AE8 (plus) +xx – that isn’t allowed by my Zero page protecting prog. |
Rick Murray (539) 13840 posts |
On my blog is an annotated version of the code explaining what it does. It is a slightly later version so it can also report on the processor flags (NZCV), plus “for the lulz” there is a description of how to use breakpoints in BASIC, not that there’s |
Colin Ferris (399) 1814 posts |
Thanks for the effort – not much ARM code info around. Does this work with 32bit RO :- tst xxxx |
Rick Murray (539) 13840 posts |
Very interesting question. It appears that the flags are not supposed to pass a SWI, though a number of artificial tests (like MOV R0, #0 and SUBS R0, R0, #1) showed the code working correctly. It is a fairly simple fix though. Push the CPSR into R1, and then MOV the uppercase version of the letter to it. If the clause is EQ, add 32 (makes it lower case). Then OS_WriteC to output it. |
Jeffrey Lee (213) 6048 posts |
Apart from kernel SWIs, which are a bit special, the official line is that NZCV is undefined on entry to a SWI handler. When the handler exits, the current NZCV flags will be passed back to the caller. So handlers can’t read the caller’s flags, and if they want to return a value in a flag they must explicitly set the flag to the right value since the input value might not match what the caller had. |
Colin Ferris (399) 1814 posts |
I supose this only effects ARM assembler writers. But if the SWI’s don’t do teq/cmp etc – no flags are changed. Justin F. (wanted used) provided a ‘Function signatures’ macro – (I have made up a BASIC version). Since the GCC assembler is open source – perhaps a few macro’s could be added as standard – like a list of common swi’s etc. Would make examples – like Ricks – easier to write. It would be nice – for ones starting out coding – to make coding as simple as possible – without piles of header files – and strange sounding errors from Assembler/C Compilers. Above – did Rick mean movs r0,#0 |
Colin Ferris (399) 1814 posts |
Using swi 256+7 – seems to allow &E0000000 through – V flag – zeroed -using the debug module BreakPt. |
Rick Murray (539) 13840 posts |
It is a pretty big IF, to have a SWI “do something” that doesn’t modify the flags. Consider something as simple as SWI 256+65 which outputs an ‘A’ to the screen. Bzzzt! Wrong. It sends an ‘A’ to the current VDU stream, which could be VDU4, VDU5, redirected to sprite, copied to serial port, etc etc. Even if it was just to the screen, RISC OS uses a bitmap display, so there is surely some flag-using logic in reading the character code from the system font buffer and plotting it pixel by pixel to the screen.
I have my own set of macros, there is a very big set of them in the DDE, plus I have (and DDE has) a long list of SWI definitions. The reason I didn’t include any of this with my program is that “useful” headers would, by necessity, be many times larger than the program code.
Marginally. It wasn’t hard to look up the SWIs I wanted in StrongHelp to get the numbers.
Generally speaking those strange sounding errors (and fear-inducing panic from the C compiler should you miss a single ‘;’) tell you that you did something wrong. Use it as a lesson – because unfortunately while we may be human and forgetful and stuff, there is zero room for error in software. You mess up, things will go wrong. You mess up a lot, it’ll blow up in your face (all those error messages), but you mess up just a little, that’s the worst as those problems can be subtle and hard to track down. As you pointed out with my SWIEQ, SWINE, and the question of whether or not SWIs preserve flags. They used to. They pretty much don’t now. I forgot.
Technically the SWI protocol states that V is set on exit if there was an error, so I guess it is valid to assume that V will be zeroed on entry to a SWI so it is only set on exit if an error actually happened. This is important to know as usually the behaviour of the SWI is modified so that R0 is a pointer to an error block, and any of the other registers that might be returned will either be preserved or in an undefined state. All you’re supposed to know is R0=error message, if V is set. |
Rick Murray (539) 13840 posts |
I’ve managed to get the breakpoint handler to enter a C module, so I’m writing something that will be entered upon OS_BreakPt but will offer more facilities (such as changing registers or flags, examining memory, etc). It isn’t designed to be a fully fledged debugger. There’s the Debugger module for those who like pain, and DDT for those who like pain with whipped cream on top. :-P |
Colin Ferris (399) 1814 posts |
Just made a ‘empty module’ – that just returns with ‘mov pc,r14’. swi Debug_0 The idea is that with ‘DeskDebug’ that it would seem easier to just type in:- Debug_0 – to set breakpoints. If you include the swi in the source code – the debugger with stop. The point is – is by adding this swi to the code – liable to have any side effects -other than making the code longer – maybe adr problems? |