ldr r0, #0x28
ldr
指令是什么?它是否从某个偏移量加载字符串?如何找到实际加载的字符串/值?
ldr r0, #0x28
ldr
指令是什么?它是否从某个偏移量加载字符串?如何找到实际加载的字符串/值?
LDR 将 32 位常量(LDRH(半字):16 位,LDRB(字节):8 位)从内存加载到指定的目标寄存器(在您的示例中为 r0)。
由于 32 位常量不能用 32 位操作码(或 16 位 Thumb 指令)编码,汇编器将常量存储在靠近引用指令的文本段中,然后使用(通常)PC 相对寻址引用该值,即与 r15 的一些偏移。
因此,ldr 实际上是一个伪指令。以下代码
.code 32
main:
ldr r0, =0x12345678
bx lr
由汇编程序翻译成
00000000 <main>:
0: e51f0000 ldr r0, [pc, #-0] ; 8 <main+0x8>
4: e12fff1e bx lr
8: 12345678 .word 0x12345678
如您所见,原始 ldr 指令中引用的常量实际上存储在地址 0x8 中,而不是存储在指令本身中。地址 0 处的 ldr 指令然后使用 PC 相对寻址引用该值。PC 的偏移量是 0(而不是 8),因为实际的 PC 值始终是当前指令的地址 + 8 - 这是早期 ARM 处理器流水线的影响,必须保留以保持兼容性。
这可以简单地翻译成:
r0 = 0x28;
在 ARM 汇编中,#
标记是立即数,而r0
, r1
, ... 是寄存器。该ldr
指令可以采用以下语法形式(第一行是你的):
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
没有=
PC 相对负载
对于标签和数字都是如此。
但是您当然很少会在程序集中直接使用数字。也许你提供了一些没有标签的拆解?
以下两个都在 GNU GAS ARMv8 中工作。带标签:
ldr x0, pc_relative_ldr
b 1f
pc_relative_ldr:
.quad 0x123456789ABCDEF0
1:
/* x0 == 0x123456789ABCDEF0 */
带有偏移量:
ldr x0, 0x8
b 1f
.quad 0x123456789ABCDEF0
1:
/* x0 == 0x123456789ABCDEF0 */
两者是等价的。汇编程序恰好为您将标签转换为正确的偏移量。
STR 没有像 ARMv8 中的 LDR 那样的 PC 相对寻址,您只需要先将地址计算到寄存器中即可:https : //stackoverflow.com/questions/28638981/howto-write-pc-relative-adressing-on-arm- asm/54480999#54480999