Acorn Arcade forums: Programming: ADR
|
ADR |
|
andrew (20:36 3/4/2005) andrew (20:38 3/4/2005) andrew (10:01 4/4/2005) Loris (10:52 4/4/2005) andrew (14:33 5/4/2005) Loris (15:44 5/4/2005) andrew (18:58 5/4/2005) adrianl (00:01 6/4/2005) Loris (10:21 6/4/2005) andrew (23:41 6/4/2005) andrew (23:45 6/4/2005) not_ginger_matt (18:08 7/4/2005) andrew (23:34 7/4/2005)
|
|
Andrew |
Message #63942, posted by andrew at 20:36, 3/4/2005 |
Handbag Boi
Posts: 3439
|
Is there a way of implementing a comprehensive version of what ADR does in BASIC assembler?
At the moment I'm subtracting the address of the label I want from the address of the instruction+8 at which I'm LDRing the difference into a register.
e.g. MVNR11,#87 BICR11,R11,#10496 \temporary reg. R11=next line+8 - 'prt' address (prt being the label)
LDR R3,[PC,R11] \ ADR R3,prt |
|
[ Log in to reply ] |
|
Andrew |
Message #63943, posted by andrew at 20:38, 3/4/2005, in reply to message #63942 |
Handbag Boi
Posts: 3439
|
In fact I'm not doing that at all am I? No wonder it's not working properly. |
|
[ Log in to reply ] |
|
Andrew |
Message #63954, posted by andrew at 10:01, 4/4/2005, in reply to message #63943 |
Handbag Boi
Posts: 3439
|
Another one mistakenly posted in the Playpen instead of Programming! |
|
[ Log in to reply ] |
|
Tony Haines |
Message #63957, posted by Loris at 10:52, 4/4/2005, in reply to message #63942 |
Ha ha, me mine, mwahahahaha
Posts: 1025
|
Why can't you just use ADR?
Address too far away?
ADR assembles to an ADD or SUB Reg,PC,#n if I remember correctly. If you want something which doesn't fit in 8 bits shifted left a multiple of two bits, it will fail. It is possible to write a macro which will use 2 or more instructions to generate the address you want.
Typically you want it to use a fixed number of instructions, so that unknown references don't cause problems. An advanced macro would be able to cope with offsets like &000FF0FF0, and might report a warning if the offset would fit in 1 instruction. |
|
[ Log in to reply ] |
|
Andrew |
Message #63989, posted by andrew at 14:33, 5/4/2005, in reply to message #63957 |
Handbag Boi
Posts: 3439
|
Yes I was using LDR for some reason instead of ADD or SUB. Is the 8 bits/multiple of two the same rule for the Operand 2 immediate constant as well? I thought it was any no. up to 4096 then that kind of rule?
How would you write an advanced macro? I take it you would have to scan all of the code from the base address until the label was encountered then do the equivalent of what !Immediate does?
I've always found the ADR limitation strange - it seems to be a makeshift, unfinished directive in what otherwise is a brilliant, free assembler. |
|
[ Log in to reply ] |
|
Tony Haines |
Message #63993, posted by Loris at 15:44, 5/4/2005, in reply to message #63989 |
Ha ha, me mine, mwahahahaha
Posts: 1025
|
Kind of. Yes, it is exactly the same rule as for operand 2, because it actually does compile to an ADD or SUB, so it is an operand 2.
The +/- 4096 is for the offset in LDR/STRs. That uses the bits available in a different way. I think it makes sense to have a larger addressable offset, rather than huge offsets only at a subset of positions.
I'm not sure what you are getting at about scanning code. First write a standard macro. This should work out the offset from PC then compile to either two (or more) ADDs or SUBs. Something like (and only like, rather than exactly, this is off the top of my head!)
DEF FNadr(reg%,adr%) offset%=adr%-(P%+8) IF offset%>0 THEN [OPT pass% ADD reg%,PC,#offset% AND &FF ADD reg%,reg%,#offset% AND &FF00 ] ELSE offset%=-offset% [OPT pass% SUB reg%,PC,#offset% AND &FF SUB reg%,reg%,#offset% AND &FF00 ] ENDIF =0
So instead of : ADR R6,datastart you would do : FNadr(6,datastart)
I might have got the offset wrong, you'll need to check the output.
So ... if that works, I hope you see how. If not, try to get it working.
Now. This will address up to &FFFF away from the program counter. You could fiddle with it to address &FFFF<<2 if you only wanted 4-byte aligned offsets, or so on. I find this good enough for most purposes. But, to get one which would work for larger values if they were possible, you should examine offset% to see if it will split into two addressible chunks. The trivial implementation is to loop testing two bits of the offset from the bottom of the word. Once this is non-zero, mask off 8 bits starting there, and repeat for the second instruction. If there is anything left over, return an error if the compilation error bit is set. If the second instruction's offset is zero, print a warning but continue to compile. |
|
[ Log in to reply ] |
|
Andrew |
Message #63996, posted by andrew at 18:58, 5/4/2005, in reply to message #63993 |
Handbag Boi
Posts: 3439
|
Thanks I didn't think of that. Might try that next. I assume BASIC then would have no problem in working out the memory address of an assembler label it had encountered? This is what I mean by scanning: I was thinking that the assembler would have to call a routine which somehow examined every 4 bytes from the start of stored code (say in DIM code%) until it encountered the assembled equivalent of the label 'prt' (or whatever). Of course your solution if it works is far better.
I'm going to have to look up what the Op.2 imm. const. rule is again as I can't really follow what you mean about working with larger numbers. I think you're describing what !Immediate does - works out a solution in two steps (hence the MVN and BIC that I originally posted).
The macro you've given though should be alright although the code is separated by some assembler arrays (i.e. equates) which are close to if not more than 64K.
[Edited by andrew at 20:00, 5/4/2005] |
|
[ Log in to reply ] |
|
Adrian Lees |
Message #63998, posted by adrianl at 00:01, 6/4/2005, in reply to message #63996 |
Member
Posts: 1637
|
I'm going to have to look up what the Op.2 imm. const. rule is again as I can't really follow what you mean about working with larger numbers. Any 8-bit number (0-255) rotated (right) by an even number of bits (0,2,4,...30) to form a 32-bit word. |
|
[ Log in to reply ] |
|
Tony Haines |
Message #64008, posted by Loris at 10:21, 6/4/2005, in reply to message #63996 |
Ha ha, me mine, mwahahahaha
Posts: 1025
|
I think you are a bit confused about what an assembler label is. When you insert a label: .label This doesn't do anything to your assembled code. Instead, it creates a Basic variable which stores the current assembly address, P% (or perhaps O% for offset assembly)
Try this:
DIM code% 16 P%=code% [ .label1 MOV R0,R0 .label2 ] P. code%,label1,label2
You should find that label1 is the same as code% and label2 is 4 more.
I vaguely remember !Immediate now. Doesn't that solve a slightly different problem? IIRC it will give you a short series of instructions which will put a given constant into a number. This is why it is using 'funny' sequences of instructions.
Constants differ from assembler labels in several respects. Offsets are relative, so ADR uses the program counter as the base. Machine code may at least in theory be executed from different addresses. So you probably shouldn't use them interchangablely. You have confused yourself now, and your code may do that again later, if you persist in doing so. |
|
[ Log in to reply ] |
|
Andrew |
Message #64048, posted by andrew at 23:41, 6/4/2005, in reply to message #64008 |
Handbag Boi
Posts: 3439
|
I aren't confused I just need to look up the immediate constant rule again as what I seem to remember reading has meshed with something else I read so it's blurred.
!Immediate simply works out if a number will be appropriate for an operand 2 value and I mot recently used it to ADR a label that was out of range (bad immediate constant). I was looking for a way for the assembler to do this without fault and I thought it would be necessary to do it /entirely/ in assembler but the BASIC/assembler macro you provided should be fine. The only alternative as I see it would be for a section of code to somehow work out the location of the label at execution time which would of course be different to what ADR does as that works out the address of the label at assembly so basically I was probably approaching it from the wrong angle. How BASIC finds the label address is another matter - I assume it puts it with the memory location addresses of all the other variables it encounters during interpretation. Not that important really - the main thing is it works |
|
[ Log in to reply ] |
|
Andrew |
Message #64050, posted by andrew at 23:45, 6/4/2005, in reply to message #64048 |
Handbag Boi
Posts: 3439
|
I say it should be fine but as mentioned above the label may be more than 64K away from the ADR so I might have to modify your macro to work with >&FFFF. |
|
[ Log in to reply ] |
|
Richard Wilson |
Message #64107, posted by not_ginger_matt at 18:08, 7/4/2005, in reply to message #64050 |
Member
Posts: 63
|
I say it should be fine but as mentioned above the label may be more than 64K away from the ADR so I might have to modify your macro to work with >&FFFF. ExtBasASM (I think that's the name) has ADRL and ADRX for this. |
|
[ Log in to reply ] |
|
Andrew |
Message #64112, posted by andrew at 23:34, 7/4/2005, in reply to message #64107 |
Handbag Boi
Posts: 3439
|
Thanks I was aware of ExtBasASM but I wanted to push myself a bit |
|
[ Log in to reply ] |
|
|
Acorn Arcade forums: Programming: ADR |