Programming Instruction
Charles Ferguson (8243) 427 posts |
Everything is different, but if you’re having difficulty seeing how to split things up by looking from the Wimp poll down, you could think about the problem differently. I suggest you don’t approach it as a wimp poll problem but as a general data problem. There’s input coming in from Wimp poll which tells you what you’re doing. There are actions that you have to take because of that. Those are the points that you should be thinking about splitting up, if you intend to do so. I would appoach it as a things that you can do. You have an applicaiton and it stores data. It can have more added to the data. It can have stuff removed from the data. It can have that data saved to disc, or to memory, and it can have the data loaded. It can be cleared. All of those operations are completely independant of the rest of the system, and can be isolated to module, library or section of the code. If you’ve got code that’s mixing interface operations and data operations then it can be split into parts. How would I appoach that sort of thing if I couldn’t see what I wanted to do? Change the problem, I think. Instead of trying to split the code up so that it’s easier to manage as a wimp application, try to split the code up so that it can be a command line tool. What I mean is, the code that you have right now that does the data storage – load, save, manipulate – should be generic enough to be used in a command line tool. Not one that does anything special, but maybe it can load a file, print out the contents and then exit. Or maybe load, apply some edits, save. Or something like that. It doesn’t have to be useful to anyone but you, because the result will be that your command line version will share all the same code, but won’t have the wimp part in it. So as you split it up, you’ll be separating the parts that are wimp or tool specific from the parts that aren’t. You could throw the command line tool away at the end… but that’s then become a testing tool that you can use as you wish to exercise the non-wimp bits of the code. By splitting it up, you don’t have to worry about the data part of the problem, and can just worry about the Wimp part. Which makes it far easier to reason about. Meh, that might not be helpful to you, but… restructuring code is hard when you’re in the depths of it… and as you untangle the mess the way tends to become clearer. |
Colin Ferris (399) 1818 posts |
Thanks for the reply. Following though the WimpPoll loop – I find tricky – *ReportTrace keeps spinning a Long list of lines or Procs. Running BasDT (32 bit) let’s me set break points on line numbers – so a bit of narrowing down of problem area. Looking at a programming book to see about dragging a save file window helps. Different tack – using a spy Prog – found that the icons in the save window have changed number. I presumed that the Prog worked before! Perhaps not. |
Martin Avison (27) 1494 posts |
WimpPoll can return to the program very frequently – if Null polls are enabled, then this is every time the Wimp is not doing antyhing, so can be many tens of thousands of times a second. Trace is not useful to debug this. If Nulls are not enabled, WimpPoll will return when any of the active reason codes are triggered – normally not that many, but some actions (eg drags) will generate a lot. Generally, more targetted debuggging is required in Wimp programs. |
Colin Ferris (399) 1818 posts |
Did think of doing - IF reason℅ <0> THEN CASE OF reason℅ ENDCASE *REPORTTRACE OFF |
Martin Avison (27) 1494 posts |
Trace can be useful, and your suggestion would decrease the output. But is is a rather blunderbus approach to debugging. I would reccomend again more targetted debugging. I tend to use something like this… |
Colin Ferris (399) 1818 posts |
I find narrowing down the problem code a problem. Once you get to grips with the code (in this case 30 year old code) you can start to pin point the Problem :-) When a very large ‘ARM Assembler (ex C’) jumps into the Boondocks – question becomes how did it get there? Being able to record the past few PC’s – would be nice – perhaps some kind of circular buffer. I wonder if Andy S version of RPCem could be made to do that? |
Colin Ferris (399) 1818 posts |
Is there a way of printing binary? A bit like Trying out A℅=20 P. V$ |
Martin Avison (27) 1494 posts |
@Colin: I am confused whether you are trying to debug BASIC or Assembler. You started by referring to PlayBack (which has both), then ReportTrace (ie BASIC), then Assembler ex C (ie not Playback). If you can assemble the code, then Reporter has SWIs you can use. In Basic assembler you can use Reporter functions. If you cannot assemble the code, then ReportPatch may help (I have even used it to debug the Wimp and other modules before source was available). Reporter has no binary output, but does have hex which is considerably more compact. |
Stuart Swales (8827) 1357 posts |
You should create space for the returned value: DIM V% 32 |
Colin Ferris (399) 1818 posts |
Am having a look at BasDT basic & Assembler at the moment. If I get stuck – time to take to dog for a walk :-) *ReportPatch ? Have made a lot of use of Report_Regs not sure how to use Report_Registers though. The large ‘C’ Prog is a 32bit version of !Picture |
Martin Avison (27) 1494 posts |
Search Reporter manual for *ReportPatch, or Help → Language Support → BASIC → BASIC Assembler functions → PROCReportPatch |
Colin Ferris (399) 1818 posts |
Ahh it’s a PROC not a star command. I was wondering if testing a swi in a module could be done by using !Zap to add a few lines to the front of the module setting up pointer to a stack (how big a stack is set up in a module at startup?) And branching to the swi address – and running a debugger to trace through the swi code. |
Martin Avison (27) 1494 posts |
Each module sets up its own stack as it wants, so there is nothing standard. Any debugging has to be proven, otherwise you can chase problems with the debugging! ReportPatch simply replaces an instruction with a branch to code added at the end, which calls Reporter and executes the displaced instruction before branching back. |
Colin Ferris (399) 1818 posts |
I thought the OS supplied the stack memory! If I have assembled the module – I add in lines like MOV R1,R1 Easy to find in !Zap. Then use !Zap to find them in the module and a replace with your Report_Regs. [Edit] If the regs are outside Report_Regs Save say R1 to a convenient memory nearby- Str r1,memory |
Martin Avison (27) 1494 posts |
Sorry, yes, for some entry points you do get r13_svc. I have always set up my own stack.
Then why not add debugging before the assembly? Saves messing with zap. |
Colin Ferris (399) 1818 posts |
Depends on how big the code ‘C’ code can be quite large :-) And it means the code stays the same length. Did try on some small modules – switching swi’s to user mode – a separate stack would be very handy. |
Colin Ferris (399) 1818 posts |
When in user mode – which areas of memory are off limits? |
Rick Murray (539) 13851 posts |
In a sane world, it would be “anything that isn’t in your application slot or a dynamic area that you own”. But, sadly, RISC OS isn’t entirely sane and you’ll find stuff giving references to days in the RMA too (among other things). I’d still stick with these being things you can access:
There’s still other stuff you can access, like the font cache or the entire module area. However just because you can doesn’t mean you should. |
Colin Ferris (399) 1818 posts |
If a module’s SWI’s were switched to user mode – what memory areas would be off limits? |
Charles Ferguson (8243) 427 posts |
I’ve not been following this thread, but if you’re suggesting that module SWIs dispatch in user mode then… no… just no. You cannot run SWIs directly in user mode without heavy caveats, so it is not a useful thing to consider. There are multiple reasons for this but the primary of these is that module code cannot assume anything about the layout of memory (as you suggest) including whether R13 is the stack pointer. Without that guarantee it is no purpose in going any further. Even accessing user mode registers is not advisable from within a SWI, but necessary in incredibly rare circumstances. |
Rick Murray (539) 13851 posts |
With you as a module? Everything you don’t actually own. Unless you’re writing a debugger, it is Just Bad to fiddle with memory belonging to anything else. PS: Previous post outlines why switching to User mode wouldn’t work anyway. ;-) |
Steve Drain (222) 1620 posts |
A while back I did run user code in a SWI call. ;-) This was in an unreleased version of Basalt where the SWIs ran code to implement routines from BASIC. In addition to user mode they also picked up the necessary high registers with some assumptions. This ran pretty well, but not in the wild. |
Colin Ferris (399) 1818 posts |
Some interesting replies – as it looks that BasDT etc are working – I’ve gone back to look into !ARM_Debug to get it working with RO 4 and RO 5 ie 26/32bit. Working in ‘ARM’ code is a bit like doing puzzles / quizzes – you either like doing it not. :-) |
Colin Ferris (399) 1818 posts |
Looking at again to see what it did. Does that in service mode switch on interrupts? How does it compare with OS_LeaveOS? |
Rick Murray (539) 13851 posts |
My 26 bit is rusty, bit doesn’t that zero all the flags? So turn on interrupts and put the processor in user mode…?
It didn’t. LeaveOS was introduced in RISC OS 5.00 (and backported via CallASWI), but a lot of 26 bit code will use the likes of TEQP to return to user mode. LeaveOS will return to user mode, as the description implies, but the call does not change interrupt status. |