LDR – 文字池 – ARM

我知道如何使用ARM中的LDR指令加载立即值。

例如:

LDR R0,=0x0804c088该指令将值( 0x0804c088 )加载到寄存器r0 。 当我尝试访问地址时,它使用gdb使用x/x $r0存储。 我收到消息: Cannot access memory at address 0x0804c088的Cannot access memory at address 。 但这不是地址,它是存储在该寄存器中的值,地址是存储在文字池中的PC相对地址。

我在那里做的错误是什么? 我明白了吗?

而且,我该如何设置文字池,你能给我一个例子吗?

@Carl Norum:这是代码。

 __asm__("LDR R0,=0x0804c088"); __asm__("LDR R1,[PC, #34];"); 

来自gdb的O / p

 (gdb) info registers r0 0x804c088 134529160 r1 0xf2c00300 4072669952 r2 0x0 0 r3 0x1 1 r4 0x8961 35169 r5 0x0 0 r6 0x0 0 r7 0xbe8f4b74 3197062004 r8 0x0 0 r9 0xef99 61337 r10 0xf00d 61453 r11 0x0 0 r12 0x0 0 sp 0xbe8f4b74 0xbe8f4b74 lr 0x89a7 35239 pc 0x8a62 0x8a62  cpsr 0x60000030 1610612784 (gdb) x/x $r0 0x804c088: Cannot access memory at address 0x804c088 (gdb) p/x$r0 $1 = 0x804c088 (gdb) p/x $r1 $2 = 0xf2c00300 (gdb) x/x $r1 0xf2c00300: Cannot access memory at address 0xf2c00300 (gdb) x/x $r15 0x8a62 : 0x1022f8df 

gdb x命令具有固有的解除引用操作。 如果要在r0打印值,只需使用p

 p/x $r0 

你正在使用的LDRforms不是真正的指令 – 它是一个汇编程序宏指令,它被转换成pc相对ldr指令和内存中某个位置的文字值(可能靠近你正在使用它的位置) 。 如果要在文字池中查找常量的地址,则需要查看输出二进制文件。 源汇编代码不包含它。

例如,让我们来看看这个简单的示例程序:

  .globl f f: ldr r0,=0x12345678 

然后构建和反汇编它:

 $ arm-none-eabi-clang -c example.s $ arm-none-eabi-objdump -d example.o example.o: file format elf32-littlearm Disassembly of section .text: 00000000 : 0: e51f0004 ldr r0, [pc, #-4] ; 4  4: 12345678 .word 0x12345678 

您可以在偏移4处看到文字就在那里。

您无需执行任何操作来“设置文字池”。 汇编程序将为您设置任何必要的文字。

如果您想在运行时知道文字池的实际地址,请尝试以下方法:

 adr r12, literal_pool_label . . . // your code here . . . literal_pool_label: .ltorg 

然后,您可以在运行时读取包含文字池地址的r12。

ltorg是强制放置文字池的指令。 对于短代码,它们自动附加在代码的末尾,但是如果代码大于4KB,LDR伪指令将在汇编时导致错误,因为pc相对偏移量大于4096,因此允许的范围。

为避免这种情况,您可以将ltorg放在代码中间,以免被误解为指令。 (以绝对分支为例)