Reputation: 171
So I have this piece of "dumb" mixed C code and ARM assembly
int main(int argc, char ** argv)
{
register int val asm("r0");
register volatile int dummy asm("r2");
register int res asm("r3");
val = atoi(argv[1]);
res = 0xfffffff;
dummy = 0xffffffff;
asm volatile(
"cmp r0, #0 \n"
"beq edest \n"
"movs r2, #0 \n"
"b fdest \n"
"edest : movs r2, #2 \n"
"fdest : add r3, r2 \n"
:
:
: "r0", "r2", "r3", "cc"
);
return res;
}
And I can't find a way to prevent the compiler to mess with it. What I mean when I say "messing with it" : - using any other registers. - interleaving instructions generated from the compilation of the C code with ones from the inline assembly (with the jump targets resolved obviously).
Basically, I want to have this exact sequence of instructions somewhere in the binary. I am cross compiling with gcc by the way, at O0.
Any hints of what I could be doing wrong?
Edit : Here is the resulting assembly for the main fonction :
00008244 <main>:
8244: 4800 ldr r0, [pc, #0] ; (8248 <main+0x4>)
8246: e92d b004 stmdb sp!, {r2, ip, sp, pc}
824a: e28d b.n 8768 <__call_exitprocs+0x20>
824c: d008 beq.n 8260 <main+0x1c>
824e: e24d b.n 86ec <strtol_l+0x28>
8250: 0008 movs r0, r1
8252: e50b b.n 7c6c <_init-0x394>
8254: 100c asrs r4, r1, #32
8256: e50b b.n 7c70 <_init-0x390>
8258: 300c adds r0, #12
825a: e51b b.n 7c94 <_init-0x36c>
825c: 3004 adds r0, #4
825e: e283 b.n 8768 <__call_exitprocs+0x20>
8260: 3000 adds r0, #0
8262: e593 b.n 7d8c <_init-0x274>
8264: 0003 movs r3, r0
8266: e1a0 b.n 85aa <_strtol_l.isra.0+0x142>
8268: 000d movs r5, r1
826a: eb00 3000 add.w r0, r0, r0, lsl #12
826e: e1a0 b.n 85b2 <_strtol_l.isra.0+0x14a>
8270: 0003 movs r3, r0
8272: e1a0 b.n 85b6 <_strtol_l.isra.0+0x14e>
8274: 320f adds r2, #15
8276: e3e0 b.n 8a3a <__retarget_lock_try_acquire_recursive+0x6>
8278: 2000 movs r0, #0
827a: e3e0 b.n 8a3e <__retarget_lock_release+0x2>
827c: 0000 movs r0, r0
827e: e350 b.n 8922 <__libc_fini_array+0x2e>
8280: 0001 movs r1, r0
8282: 0a00 lsrs r0, r0, #8
8284: 2000 movs r0, #0
8286: e3b0 b.n 89ea <__locale_ctype_ptr+0x16>
8288: 0000 movs r0, r0
828a: ea00 2002 and.w r0, r0, r2, lsl #8
0000828c <edest>:
828c: 2002 movs r0, #2
828e: e3b0 b.n 89f2 <__locale_ctype_ptr+0x1e>
00008290 <fdest>:
8290: 3002 adds r0, #2
8292: e083 b.n 839c <memset+0x48>
8294: 0003 movs r3, r0
8296: e1a0 b.n 85da <_strtol_l.isra.0+0x172>
8298: d004 beq.n 82a4 <atoi>
829a: e24b b.n 8734 <strtol+0x38>
829c: 4800 ldr r0, [pc, #0] ; (82a0 <fdest+0x10>)
829e: e8bd ff1e ldmia.w sp!, {r1, r2, r3, r4, r8, r9, sl, fp, ip, sp, lr, pc}
82a2: e12f b.n 8504 <_strtol_l.isra.0+0x9c>
It is so messed up, it is hard to match the original inline assembly with the final instructions
Upvotes: 2
Views: 343
Reputation: 171
The disassembly is wrong. You are assembling ARM code and then disassembling Thumb code. – user253751 7 mins ago
Adding some compilation (-mcpu=cortex-m4 -mthumb) options did the trick.
Upvotes: 3
Reputation: 215617
You have to constrain the asm inputs/outputs:
asm volatile(
"cmp r0, #0 \n"
"beq edest \n"
"movs r2, #0 \n"
"b fdest \n"
"edest : movs r2, #2 \n"
"fdest : add r3, r2 \n"
: "+r"(val), "+r"(dummy), "+r"(res)
:
: "cc"
);
You could also remove the bindings to particular registers and instead use %0
, %1
, etc. in your asm to let the compiler assign them, but the above should work.
Upvotes: 2