This is the disassembly of syscall() on iPhone.
(gdb) disass syscall
Dump of assembler code for function syscall:
0x3195fafc <syscall+0>: mov r12, sp
0x3195fb00 <syscall+4>: push {r4, r5, r6, r8}
0x3195fb04 <syscall+8>: ldm r12, {r4, r5, r6}
0x3195fb08 <syscall+12>: mov r12, #0 ; 0x0
0x3195fb0c <syscall+16>: svc 0x00000080
0x3195fb10 <syscall+20>: pop {r4, r5, r6, r8}
0x3195fb14 <syscall+24>: bcc 0x3195fb2c <syscall+48>
0x3195fb18 <syscall+28>: ldr r12, [pc, #4] ; 0x3195fb24 <syscall+40>
0x3195fb1c <syscall+32>: ldr r12, [pc, r12]
0x3195fb20 <syscall+36>: b 0x3195fb28 <syscall+44>
0x3195fb24 <syscall+40>: cfldrdeq mvd15, [r12], #992
0x3195fb28 <syscall+44>: bx r12
0x3195fb2c <syscall+48>: bx lr
End of assembler dump.
-
Can someone please explain what instructions at offsets +28,+32 are doing? At +28, the value of r12 is 0 (set at +12), so looks like r12 is being set to (in C notation) *(pc + 4). At +32, r12 is set to *(pc + r12) – note that this instruction is not compiling – see #3 below. The ‘b’ at +36 jumps to +44, which returns to the address in r12. So what value was loaded into r12 by +28 & +32?
-
What does the cfldrdeq instruction at +40 do? I have check the ARM instruction set & searched for it, but not found anything.
-
I added this code to my C program using asm(). When compiling, the compiler shows these errors. Any idea how to get around this?
/var/folders/62/3px_xsd56ml5gz18lp8dptjc0000gv/T//ccDThXFx.s:7607:cannot use register index with PC-relative addressing —ldr r12,[pc,r12]'cfldrdeq mvd15,[r12],#992′
/var/folders/62/3px_xsd56ml5gz18lp8dptjc0000gv/T//ccDThXFx.s:7609:selected processor does
not support
It makes more sense if you know of the small gotcha surrounding reading the PC: most instructions that read PC see a value of address_of_current_instruction+8 (except +4 in thumb mode, and
ldmin ARM mode might be either +8 or +12 IIRC).cfldrdeq mvd15, [r12], #992is not meant to be an instruction; it’s a relative relocation that points to a relocation the DATA section. In the DATA section, there’ll be a dynamic relocation that points to the actual address. Typical seudocode looks something like thisI do not know why the disassembly for
syscall()places “foo” betweenldr r12,[pc,r12]andbx r12, causing the branch over the non-instruction “foo”.It is also worth mentioning that simply pasting the code shown will almost certainly not work: you don’t have the relocation that points to the actual implementation of syscall (in a debugger, step past
bx r12and you should get there); you’ll just branch to some randomish address.The error “cannot use register index with PC-relative addressing” is apparently because you’re compiling in Thumb mode (the listing is ARM code). As for
cfldrdeq, I believe it’s just a conditionalcfldrdinstruction (the “eq” is a condition code), which Google suggests is related to a the Cirrus Logic “Maverick” processor series.