#14338 - poslundc - Mon Jan 05, 2004 5:57 pm
I've been wondering on occasion if there's any way to dynamically generate a pointer to somewhere in local memory.
That is to say, I can easily create a pointer and load it in with a ldr statement, such as in the following simple function that takes a pointer to a string and copies another constant string from local memory into it:
Code: |
TestFn:
ldr r1, .L_TEST
.STRING_LOOP:
ldrb r2, [r1], #1
cmp r2, #0
bxeq lr
strb r2, [r0], #1
b .STRING_LOOP
.L_TEST:
.word .L_TEST + 4
.asciz "This is a test" |
In this case, 4 bytes were wasted storing a fairly redundant word that just pointed to the next word ahead, and I had to use a load statement just to get a value that is a constant offset of the PC. Shouldn't I be able to do some arithmetic with the program counter instead? Something like:
add r1, pc, #.L_TEST
(Which I've tried, and doesn't work.)
Is there a way of doing this? I'm very curious to know.
Dan.
#14349 - DekuTree64 - Mon Jan 05, 2004 6:58 pm
Yeah, it's a pseudo-op called adr. It's actually done with an add on the processor, so it is possible to count up the instructions by hand and type in the offset yourself, but adr makes the assembler do it for you. So for your example, it would be
adr r1, .L_TEST
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#14357 - poslundc - Mon Jan 05, 2004 8:01 pm
Well now I know. Is there a source somewhere for these nifty pseudo-ops?
Dan.
#14362 - Paul Shirley - Mon Jan 05, 2004 8:53 pm
removed
Last edited by Paul Shirley on Sun Mar 28, 2004 9:22 pm; edited 1 time in total
#14366 - poslundc - Mon Jan 05, 2004 9:28 pm
I've been working off the ARM7TDMI data sheet for ages, and the only references I've found for the adr pseudo-instruction were it being used in a couple of examples for the bx instruction and the swi instruction, with no explanation as to what it did. The lea pseudo-instruction was nowhere to be found.
Are these pseudo-ops characteristic of the processor, or the assembler?
Dan.
#14382 - DekuTree64 - Mon Jan 05, 2004 10:48 pm
The only 2 pseudo-ops I was aware of were adr (which turns to add reg, pc, #ofs) and nop (mov r0, r0). I tried lea and got a bad instruction error. I think that was an instruction on x86 processors, but not ARM.
Anyway, I learned them from GBATEK, down in the processor info section
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#14391 - tepples - Mon Jan 05, 2004 11:32 pm
Like the numerous MIPS macros, these ARM pseudo-ops (ldr =, adr) seem to be assembler-implemented macros.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#14397 - Paul Shirley - Tue Jan 06, 2004 12:06 am
removed
Last edited by Paul Shirley on Sun Mar 28, 2004 9:23 pm; edited 1 time in total
#14430 - torne - Tue Jan 06, 2004 4:20 pm
adr and various other pseudo-ops are implemented by the assembler and are translated into real machine instructions. They are pretty standard; the same ones work in GNU as and in the ARM development kit. The info file for as will list them, under the Machine Dependencies section.
#14895 - sasq - Wed Jan 14, 2004 3:08 pm
Just do
add r0, pc, #label-.-2
in gas, or
add r0, pc, #label-?-2
in goldarm, provided label is 32bit aligned.
Besides not wasting space, this type of coding also has the nice benefit of being completely relocatable.
#14901 - poslundc - Wed Jan 14, 2004 4:46 pm
sasq wrote: |
Just do
add r0, pc, #label-.-2
in gas, or
add r0, pc, #label-?-2
in goldarm, provided label is 32bit aligned.
Besides not wasting space, this type of coding also has the nice benefit of being completely relocatable. |
I tried something similar to this in gas, and it wouldn't assemble. :P
Dan.
#14904 - sasq - Wed Jan 14, 2004 5:15 pm
Well similar isn't same - and that works. The important bit is that "." means current adress so the expression evaluates to something small enough for an add.
#14905 - poslundc - Wed Jan 14, 2004 5:58 pm
Interesting, I'll have to give it a try. I was always under the impression that labels were generated relative to the program counter to begin with.
Dan.
#14920 - torne - Wed Jan 14, 2004 8:21 pm
The adr pseudo-op does exactly the same as the above add, but with the added benefit that it will automatically generate a load and store the address in a literal pool if it's out of range, whereas the add will fail. Just use adr. =)
#14929 - poslundc - Wed Jan 14, 2004 8:38 pm
Does that mean I need to use a .pool directive if I'm going to use adr? 'Cos I don't normally include a .pool directive... (I like to assemble/load my constants myself.)
Dan.
#14931 - jma - Wed Jan 14, 2004 9:23 pm
Using LEA (I don't know ADR) you should not need a .POOL directive. This is because the assembler should insert an ADD rd,PC,# instruction.
Jeff
_________________
massung@gmail.com
http://www.retrobyte.org
#14944 - torne - Thu Jan 15, 2004 1:31 am
adr only uses the pool if the address generated is out of range. You don't need a .pool directive most of the time anyway, as the pool will be dumped at each section change automatically. The .pool (or .ltorg) directive is just a hint to dump it early.