3

I have a small question about using ASM in c. I want to execute the instruction:

LDR PC,=0x123456

This gives me the error "unexpected token in operand".

asm("LDR PC,=0x123456");

This gives "invalid constraint".

asm("LDR PC," : "m" (0x123456));

What's the right way to do this?

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
Janosch Hübner
  • 1,584
  • 25
  • 44
  • 9
    Which C compiler are we talking about here? – Timo Geusch Sep 25 '13 at 14:07
  • inline assembly is not supported on all compilers - e.g. sun sparc - and, if it is, is compiler-specific – Bathsheba Sep 25 '13 at 14:09
  • By invalid `constrant` you mean `constraint` right? – Shahbaz Sep 25 '13 at 14:09
  • why not just branch to that address in C and not mess with asm? – old_timer Sep 25 '13 at 14:11
  • or do it in real asm and not inline? you probably want to use bx not ldr anyway so a copy to r0 then bx r0 doesnt cost you really any more by using asm vs inline. – old_timer Sep 25 '13 at 14:12
  • I want to load pc to a different position (code cave). I am using clang to compile it by the way – Janosch Hübner Sep 25 '13 at 14:32
  • Why not just invoke the code if that is a routine or perform a jump? – Artur Sep 25 '13 at 14:50
  • 1
    Some reading: [ldr vs mov](http://stackoverflow.com/questions/14046686/ldr-vs-mov-arm-assembly), [replace ldr with b](http://stackoverflow.com/questions/17428025/why-ldr-cannot-replace-with-b), [Placing address in a register](http://stackoverflow.com/questions/15774581/placing-the-address-a-register-is-pointing-at-in-to-a-register), [LDR literal pool](http://stackoverflow.com/questions/17680185/ldr-literal-pool-arm), etc. [ARM+ldr+equals](http://stackoverflow.com/search?q=[arm]+ldr+%3D) – artless noise Sep 25 '13 at 17:05

3 Answers3

2

You are using this:

asm("LDR PC,=0x123456");

This is not a standard ARM assembly instruction, but a pseudo-instruction provided as a compiler extension. This pseudo-instruction is converted to other assembly instructions when you compile it. It seems clang doesn't support this compiler extension (see this thread). You should do the conversion to assembly instructions yourself, see the ARM documentation for how the LDR pseudo-instruction is converted.

Étienne
  • 4,773
  • 2
  • 33
  • 58
0

You can probably achieve the effect you want in plain C:

((void (*)(void))0x123456)();

or if you prefer more verbose:

typedef void FN(void);
((FN*)0x123456)();
scott
  • 728
  • 4
  • 8
0

I agree with @Étienne. I tried you code with mi Google toolchain. It's working fine.

I think you should read the manual how the compiler changes the directive to instructions (normally two mov instructions).

TwoCode
  • 127
  • 7