ldr r0, #0x28
What is the ldr
instruction ? Does it load a string from some offset?
How can I find the string/value that is actually loaded ?
Reverse Engineering Stack Exchange is a question and answer site for researchers and developers who explore the principles of a system through analysis of its structure, function, and operation. It only takes a minute to sign up.
Sign up to join this communityLDR loads a 32-bit constant (LDRH (halfword): 16 bit, LDRB (byte): 8 bit) from memory into the specified target register (r0 in your example).
Since 32-bit constants cannot be encoded in 32-bit opcodes (or 16-bit for Thumb instructions), the assembler stores the constant in the text segment close to the referencing instruction and then references the value using (usually) PC-relative addressing, i.e. some offset from r15.
Thus, ldr is in fact a pseudo instruction. The following code
.code 32
main:
ldr r0, =0x12345678
bx lr
is translated by the assembler into
00000000 <main>:
0: e51f0000 ldr r0, [pc, #-0] ; 8 <main+0x8>
4: e12fff1e bx lr
8: 12345678 .word 0x12345678
As you can see, the constant referenced in the original ldr instruction is in fact stored at address 0x8 instead of in the instruction itself. The ldr instruction at address 0 then references this value using PC-relative addressing. The offset to the PC is 0 (instead of 8), since the actual PC value is always the address of the current instruction + 8 - this is an effect of the early ARM processor pipeline which has to be preserved for compatibility.
This can be simply translated into:
r0 = 0x28;
In ARM assembly, the #
marks the immediate values and the r0
, r1
, ... are registers. The ldr
instruction can take the following syntactic forms (yours is the first line):
LDR{type}{cond} Rt, [Rn {, #offset}] ; immediate offset
LDR{type}{cond} Rt, [Rn, #offset]! ; pre-indexed
LDR{type}{cond} Rt, [Rn], #offset ; post-indexed
LDRD{cond} Rt, Rt2, [Rn {, #offset}] ; immediate offset, doubleword
LDRD{cond} Rt, Rt2, [Rn, #offset]! ; pre-indexed, doubleword
LDRD{cond} Rt, Rt2, [Rn], #offset ; post-indexed, doubleword
ldr
without =
does PC relative loads
This is true for both labels and numbers.
But you will of course rarely use numbers directly in your assembly. Maybe you have provided some disassembly without labels?
Both of the following work in GNU GAS ARMv8. With a label:
ldr x0, pc_relative_ldr
b 1f
pc_relative_ldr:
.quad 0x123456789ABCDEF0
1:
/* x0 == 0x123456789ABCDEF0 */
with an offset:
ldr x0, 0x8
b 1f
.quad 0x123456789ABCDEF0
1:
/* x0 == 0x123456789ABCDEF0 */
Both are equivalent. The assembler just happens to convert the label into the correct offset for you.
GitHub upstream with assertions.
STR does not have PC-relative addressing like LDR in ARMv8, you just have to calculate the address into registers first: https://stackoverflow.com/questions/28638981/howto-write-pc-relative-adressing-on-arm-asm/54480999#54480999
#0x28
and not=#0x28
?