*LOADing GCC binaries into BASIC
Pages: 1 2
Daryl Dudey (2012) 55 posts |
So, as the title says, it must be possible to call GCC produced machine code from BBC BASIC. I presume I need to allocate a large enough area and then know the magic address offsets to CALL into? Before I start running the disassembler and trying to figure this out, has anybody done it before? I could see needing a small BBC BASIC assembly stub to call through to it to set registers up maybe? Or just create a module. Cheers, PS. I suppose it’s entirely possible it’s not possible. Maybe GCC adds funky setup and exit code. Maybe it calls SWIs that affect the current running environment. Maybe it’s not just a simple binary blob I can drop into… PPS. Disassembly shows it’s set to run at 0×8000, attempting to create a position independent executable gives me build errors. I suspect this might solve a lot of my problems… |
Rick Murray (539) 13840 posts |
A proper program, using the C runtime (whether DDE or GCC) will set up a complete environment for the program, which will replace BASIC. If this is what you want, then just run it and let the OS sort out the mess. It gets harder if you plan to run the program and then return to BASIC. This involves moving the entire BASIC environment up in memory, loading and running the program, and on exit moving the BASIC environment back down. This is because “applications run at &8000 on RISC OS”. If, instead, you are planning on calling library functions from BASIC, then you’ll need to manage not only BASIC’s runtime environment, but enough of C’s to get it to work. That’s why binary blobs written for BASIC are written directly in assembler. That way you can know the exact specifics of how it works, without the additional complications that C introduces (like stack frames, memory allocations, APCS, the magical R10, and so on). This might provide some pointers (but it’s aimed at the DDE): https://www.riscosopen.org/wiki/documentation/show/Using%20C%20in%20assembler%20components Generally, however, people don’t mix C and BASIC. |
nemo (145) 2546 posts |
I have occasionally investigated the feasibility of persuading BASIC to be less rigid about where it finds itself. It’s happy for the program to be anywhere in memory (PAGE), and accesses its static memory via a single register… but unfortunately it tends to reset that pointer at crucial intervals, during error handling for example. It’s a shame, as it’s a gnat’s whisker from being entirely relocatable. I have often wanted to put a BASIC instance in a Dynamic Area for… reasons. It could be persuaded to be more flexible, but at the expense of some resilience to register corruption. Another feature for ICantBelieveItsNotBASIC I suppose. Aside: Despite being happy for PAGE to be anywhere in memory, and despite ROM-based programs like Alarm actually running from ROM via the usual ResourceFS internal handle hackery, BASIC doesn’t actually do so automatically. It’s one of the few modules that steadfastly refuses to treat ResFS specially. It would have been nice to have a command line option to enable the wheeze. |
Daryl Dudey (2012) 55 posts |
Thanks chaps, I really appreciate the advice. It is as a I suspected, a standalone app does a bunch of setting things up, which BASIC will obviously not be expecting to happen (it’s already set things like the stack up). I have two options, be super clever and write something that will take the GCC .S files output and convert (tedious but doable) or re-code things in BASIC assembly language by hand. Or third option is I continue my work in GCC, but I really WOULD like the ability to call my 3D stuff direct from BASIC (think updating the positions of entities). Thanks for the help as always :-) |
Daryl Dudey (2012) 55 posts |
BTW, the forum is driving me crazy!! |
Rick Murray (539) 13840 posts |
A little detail missing from your original post. Can’t you tell the linker to spit out a raw binary file, so you get just the assembler without any sort of “this is a program” wrapper? On DDE, it’s You can then load that binary into BASIC and Then there are two ways of dealing with this. The first is to hardcode offsets into BASIC, like The second is to prefix the code with a table of branches, so you |
Rick Murray (539) 13840 posts |
For the forum, “simply” go to the login page, clear the riscosopen.org cookies, then log in. If you don’t clear the cookies, your chance of getting logged in is about the same as predicting what’ll happen with Brexit next week… |
John Williams (567) 768 posts |
Then why hasn’t someone devised a simple (RISC OS) Obeyfile to parse and alter NetSurf’s cookies file to do this and then log-in as with the HTML pre-loaded log-in page previously advocated? Sorry – it doesn’t seem to incorporate a source, but its title field is: RISC OS Open: Single sign-on: Log in. The whole thing seems so trivial I might even be able to do it myself! But hesitate … I’d been firmly told earlier that such problems were in the past! Rick, go’on, go’on, go’on, go’on, |
Rick Murray (539) 13840 posts |
If I was going to bother doing it, it would be a WebExtension, because I use Firefox much more than I use NetSurf. However, clearing cookies on either isn’t arduous, so I’ve not been annoyed enough to expend the time and energy in doing something about it. That said, the fix really ought to be done at server side, not client side. Until then, it might be useful to paste a big note on the login page to advise clearing cookies. As this topic (as all the others before) demonstrate that it’s not an expected behaviour and we don’t really want to put potential visitors/developers off right at the beginning when the “bodge” is so simple… |
Martin Avison (27) 1494 posts |
It is strange though that I login on Win Firefox most days, and RO Netsurf not quite so frequently, and I think I have had a problem only once! It does not affect everyone … for some reason. |
Daryl Dudey (2012) 55 posts |
I actually did this with the “prototype”, where I had line drawing and simple transformation stuff done in inline assembly in BASIC. I then decided that, although the performance was great, it was vastly time consuming and I would never get anything done. It’s FAR more sensible to write it in a compiled language and then optimise the hotspots where it matters. I know some claim that ARM is easier than C, but I think they probably have a bit of Stockholm Syndrome! |
Daryl Dudey (2012) 55 posts |
A look at the —help for ld does give some interesting options, such as marking no stack required and pic (which on x64 at least is position independent code). I’ll have to have a play around, see what I can come up with. |
Daryl Dudey (2012) 55 posts |
So, using ARMalyser and hex dump for some things. I can see the entry point is &C, which has a BL to the right place. Now, it seems to be checking the SharedCLibrary version and then jumps to SharedCLib Func: _kernel_init. I get an output of Unknown library chunk. It’s still probably trying to initialise the program space and dropping out, I feel it’s a dead end, but it’s fun at least trying! |
David Feugey (2125) 2709 posts |
Very good idea. Another option would be to code a simple compiler that could generate BBC Basic ASM code. difficult, but doable. |
Rick Murray (539) 13840 posts |
Yes, of it is C and not assembler, that complicates matters with respect to using it from BASIC.
Certainly – that way you can concentrate on writing code and not upon appeasing the processor.
People that don’t know C? ;-) |
David Feugey (2125) 2709 posts |
It’s FAR more sensible: The two are equals for me. |
Daryl Dudey (2012) 55 posts |
This would be the obvious course of action to take, however after speaking to others the suggestion is having something that can be called from BASIC to make it more accessible. I’ll see where I end up.
To a point yes, but I’m doing 3D stuff and BASIC is sorely lacking in data structures. Unfortunately about 80% of the code is speed critical otherwise the frame rate drops too low. ARM BASIC is at least very fast, but not quite fast enough. |
Steve Drain (222) 1620 posts |
Me too. ;-)
The program is essentially a script and I have put that everywhere I could think of and it seems happy.
That reliance on ARGP in R8, but the use of the R8 for other purposes in some routines is a real bugbear. I have assembled BASIC, under another name, with ARGP at other values than &8700 and happily run programs with it.
A BASIC /program/ can run from a dynamic area, but that is not quite what you mean. My Basil module puts BASIC /libraries/ in the RMA and lets them be shared among any number of programs. For fun, I also wrote a module that allowed its *commands to be written in BASIC, but they had to be a task so used the minimum 4k wimp slot for the BASIC arguments. Given that 4k minimum you can juggle with PAGE, TOP, LOMEM, HIMEM and MEMLIMIT to place the other memory requirements in non-task slots, but I have not fully explored the consequences. ;-)
I almost did something like that with my RFSFiles module, but stuck with only dealing with BASIC files as libraries, not programs. |
nemo (145) 2546 posts |
Yes, the misuse of R8 (because we know what it holds!) is only a head-scratcher in one place. The rest are easy. The biggest problem is the knock-on effect of addresses getting b30 & 31 set. Uggh. |
Steve Drain (222) 1620 posts |
In the original post:
Expanding on that, write your module with the routines as SWIs to be called from BASIC. If the overhead is too much, have a base SWI that returns the address of the SWI jump table and pursue the option mentioned above of To go the whole hog of integrating with BASIC you could subvert the way |
Daryl Dudey (2012) 55 posts |
I looked online to see how to write a module with GCC, I can see the link option to do the module relocatable stuff, but a tutorial would be very easy so I can set all the required module stuff. It would definitely be the way to go. Like you say, my code can be called through SWIs or through a memory address to jump to the required routine. RISC OS is a lot of fun, but it can be tricky to find stuff online sometimes :-) |
nemo (145) 2546 posts |
Steve Fermat suggested
Hmm. I would always recommend indirecting such linked jump tables through a separate discoverable RMA veneer, so that if the module is killed while clients are still running they do not start calling random bits of whatever else happens to get loaded into that part of the RMA. In lieu of any better registrant, ResFS is acceptable. So… 1. Library module starts Thus the jump table is persistent but the module can be reloaded. The client API is identical to Steve’s suggestion, but it’s more reliable. [BTW I’d recommend leaving some spare jump addresses so that a later version of the module can reuse the jump table created by an earlier version] |
Daryl Dudey (2012) 55 posts |
Ah, just found the module example i the !GCC directory. I don’t have time right now, but I’ll take a look at it later. |
Steve Drain (222) 1620 posts |
Yes, of course. Basalt does that for its link. In one of its incarnations it also provides a separate table in RMA to useful internal routines that is updated when the module is restarted. An alternative might be to count users and refuse to die, but this is getting quite detailed enough already. ;-) |
Jeffrey Lee (213) 6048 posts |
One thing to bear in mind is that cmunge (the tool GCC uses to create the module header/stubs) is basically an open-source clone of the CMHG tool that comes with the commercial DDE. If you don’t own a copy of the DDE, there’s an old CMHG manual available online here which should cover all of the important stuff (although the documentation is written under the assumption that you already know how modules work!) |
Pages: 1 2