BASIC assembler help
David J. Ruck (33) 1635 posts |
You were using the correct OPT number before every chunk of assembler? |
Alan Adams (2486) 1149 posts |
The main loop and every function each start [OPT pass%. The loop is FOR pass% = 8 TO 11 STEP 3. I did discover an oddity in that commenting out a function reference with either or both of REM and ; does nothing – the function is still assembled. |
Rick Murray (539) 13840 posts |
Ah, yes. I recall how utterly expensive Desktop C was. When I bought my A5000 (guy wanted to sell it to get a first issue RiscPC I think), I thought the price was a little high so I haggled and got some bundled software. Some games that I sucked at, some version of Impression that I didn’t like (sorry, Ovation clicked with my way of thinking, Impression didn’t (plus in those days it was kind of fugly)), and the C stuff with all the manuals. Win! ;-) I think in those days, too, there would have been a lot of K&R style C. Which is a bit of a mess. It probably doesn’t help that C is flexible to the point of becoming gibberish by intent (Google the obfuscated C contest). But once you become more familiar with it, it starts to make sense. Now, Lua, that’s a write-only pile of punctuation symbols. <poke><poke> Hello Gavin! |
Steve Fryatt (216) 2105 posts |
It’s not something as simple as the fact that comments in the assembler block are |
Steve Fryatt (216) 2105 posts |
It’s quite possible for BASIC to be “write-only”, too. It’s down to how the code is written, not the language (and BASIC, with its lack of self-documenting structures, is pretty grim once you have a fair-sized Wimp application). |
Steve Pampling (1551) 8170 posts |
I think you would agree that the transparency/opaqueness is largely down to the habits of the code author – which you covered in this:
It might be interesting to see a language where the bad/opaque code writing isn’t possible, but I don’t think one exists at present. |
Alan Adams (2486) 1149 posts |
Wasn’t that part of the rationale behind ADA. (Where “Hello World” compiled to 5 pages of code.)
I might be misunderstanding here, but when I put a : in a comment, the bit after was reported as “unknown operand”. Surely comments begin ; ? in this case the following all get assembled: ; FNtest |
Steve Pampling (1551) 8170 posts |
When you put a : into it the BASIC interpreter sees it as the start of a new command as much so as if you’d hit the enter key for a new line and then typed the remainder of the text. Suffice to say BASIC assembler != objasm |
Steve Fryatt (216) 2105 posts |
But not in the context that I gave. A
However, that’s not the case in the assembler. There, both
If you’re a fan of multi-line statements, then the following might (or might not) have a surprise in store:
The comparison that I was making was between BASIC and the BASIC Assembler, which has long been a trap for the unwary. PS. IIRC, and off the top of my head, this is why the BASIC assembler will accept both tokens and untokenised text for its instructions. |
GavinWraith (26) 1563 posts |
As Steve says, it is down to how it is written. I have just put here a small and probably unnecessary application Multisave . As Druck said, an edge case , for when you want to save stuff to lots of directories simultaneously. It is written more for annotation than for use. The program is written as four chunks, each commented for what variables it consumes ( uses ) and what it provides ( exports ). The catch is that you have to read the last chunk first to understand what is happening, because Lua’s operational semantics demand that definitions precede use. It certainly looks as if the syntax of BASIC and that of the BASIC Assembler were not designed together. Perhaps designed is not the mot juste in this case. The idea of combining two languages, one low-level the other higher-level, is brilliant, however. Lua and C is another such pairing. I am not sure that the goal of having a really readable programming language is such a good one. It has so often been a trap. Expressivity and readability often pull in opposite directions. |
Martin Avison (27) 1494 posts |
Sorry, but I cannot let these two earlier statements go unchallenged, as surely they are both wrong…
BASIC variables xxx and xxx% are different – see the following code snippet: which gives:
Both REM and ; comment an assembled line up to the next colon or the end of the line – see the following code snippet: which gives:
But I may have misunderstood what you were saying. |
Steve Drain (222) 1620 posts |
Here’s just little more to add to the assembler comment gotchas. If you have Basic$Crunch set, then a REM and the rest of the line are removed, and Steve F’s REM ADR RO, my_data% : LDR R1,[R0] gotcha will disappear. The colon for the next instruction can be in a string , so beware commenting out something like this: ;TEQ r0,#ASC":" ; is character a colon Fun, isn’t it. ;-) |
Steffen Huber (91) 1953 posts |
“Hello World” in Ada is reasonably compact, mostly consisting of the usual ceremony to import the standard lib to print a string. It depends who you ask, but the Ada rationale includes various different goals:
In some ways, it could be said that Ada is the complete opposite of BBC BASIC. |
Alan Adams (2486) 1149 posts |
So I’m still fighting the assembler. I got the code to assemble, and run without crashing the machine. Now I’m debugging the program logic, which is not quite right. AS I make minor changes, which are still valid code I apparently randomly get For the unknown BASIC variables I added some *report commands here:
On the first pass the *report give "status%=16 pass%=8 Sometimes the second pass gives "status% pass%=11 (i.e. no value now known for status%) IMMEDIATELY followed by an access violation within either BASIC or Reporter. EDIT I just tried with Basic$crunch = 1, and the access violation disappeared, and it compiled correctly. So that’s pasted over the problem for now. Steve’s example comment is one I would not have thought of, so it gives me something to look for. |
GavinWraith (26) 1563 posts |
On the topic of why there is no one language to rule them all, I recommend this video . |
Steve Drain (222) 1620 posts |
P%=address% FOR pass%=8TO11STEP3 P% must be set to address% inside the FOR…NEXT loop. Otherwise your code is being assembled at the value of P% after the first pass. This is writing over the top of heap objects, such as the variables that are going missing. There will be other consequences. |
Alan Adams (2486) 1149 posts |
I’ve put the program, as it will demonstrate the Assembler problem, here http://www.adamshome.org.uk/RiscOS/Assembler_Test.zip It’s a zip file containing enough to attempt to assemble the code, and text file describing what does and doesn’t allow it to work. It fails without Basic$crunch on both RO5.28 and 5.29 (ARMX6). It works with Basic$crunch = 1 on both. Minor changes to a *report command can change the faulty behaviour from Access Violation to Undefined Variable. I’m baffled. |
Alan Adams (2486) 1149 posts |
I’ve just checked. It is set inside the loop. I made a mistake typing in the example.
I suspect this might be part of my problem. I’ve typed all the opcodes in uppercase. StrongED is highlighting AND and OR as keywords, along with a few others, and rather annoyingly it is converting some words typed in lowercase into uppercase and making them keywords too. Mostly (only?) that is occurring in comments though. Would Basic$Crunch fix the AND / OR keywords issue? I’ve stopped for tonight. I think I’ll start tomorrow by lowercasing the code and see if it makes a difference. |
Rick Murray (539) 13840 posts |
That would be strange if so… I’ve always written assembler in upper case. |
Steve Fryatt (216) 2105 posts |
What’s the logic behind claiming the memory for assembling into? You set If you look at the assembly, it starts at &20000 and finishes the first pass at &20540. However, checking the memory allocation in Reporter tells me that
I think that means that you’re running off the end of your first block of memory (at To be honest, I’m not quite sure why you can’t replace
with the slightly clearer
The stuff about “extending” the allocation seems to be assuming way too much about how BASIC allocates its storage – not least because you’re creating variables in between the various If what you’re trying to do is to assemble the code to be loaded and run later on at &10000, then do that using offset assembly:
However, I suspect that you would be better ensuring that your code is relocatable.
I think that all of your problems (the crashes, lost variables, % suffixes being “optional” on label variables, dubious macro handling… the lot) are very likely down to the fact that your code would appear to be trampling BASIC’s memory as it goes. The list of problems that you’ve given in this thread are far, far too serious for them to have survived unnoticed up to now, but all shout “memory corruption” very loudly indeed. |
Martin Avison (27) 1494 posts |
Edit: Steve beat me to it! codespace% is certainly the root of a lot of problems. As Steve says, fix that and most (all?) of your strange happenings will vanish. |
Martin Avison (27) 1494 posts |
Indeed, using after the first pass, so it is obvious that the assembly has corrupted memory, where and with what.
|
Steve Fryatt (216) 2105 posts |
PS… I’ve just realised that this could screw up your setting of
instead of setting to the address at which the code is being assembled, but again – ARM code allows you to make your code independent of location very easily indeed. You should not need to bake fixed addresses into your code like this. At the start of the code, you seem to be creating a bunch of labels to actual addresses and then duplicating them as a collection of fixed offsets in the integer counterparts of the variables. Is there any reason for not deleting
and then replacing the initial block of EQUDs with something like
You would need to change a couple of
and similar with
but you’re doing that everywhere else anyway.
All untested, as I can’t easily run the code. It feels like a much more conventional way to do things, though. Multiple sets of variables pointing into the same thing will always come back to bite later on. PPS. It would be better still to make that opening block something like
and then initialise
Again, just personal preference, but then R12 does, indeed, point to the start of your variable storage. I’ve had a very cursory look at where |
Steve Fryatt (216) 2105 posts |
Hm. I should probably stop thinking about this, but there’s something else rather disturbing about your code. Edit 20-03-2001: On reflection, this isn’t quite true. It’s certainly confusing, but my concerns about the use of absolute addressing were wrong. However, the point about making life much harder for yourself stands – in fact, it’s even more true. If I’ve understood the comments in If I’m correct, then forget all of the stuff in the previous post about
Now, you can return to your opening code of
because all of the labels will be offsets from the target assembly address of zero. You can also return to doing
because offsetting Edit 20-03-2001: The bit which followed about needing to index all LDRs and STRs through R12 was complete garbage; it’s clearly been a while since I’ve written any ARM code that didn’t reside in a module. However, it does lead to a different observation, which I’ll stick in a follow-up post to keep things separate. A better approach might be to allocate the workspace separately through OS_Module, and pass the address in to this code so that R12 can be pointed to it. Then you pull all of the EQUD’s out of the assembly and do a conventional module-style workspace offset label allocation. |
David J. Ruck (33) 1635 posts |
There are one or two very specific reasons to directly place code in the RMA, but the general advice is DO NOT DO IT. Code in the RMA should be in the form of a module; so it can be loaded and initialised on demand, is visible to the user explaining a clear purpose, and removable when no longer required. |