LDR - 文字池 - ARM [英] LDR - Literal pool - ARM
问题描述
我知道如何使用LDR指令在ARM加载一个直接的价值。
例如:
LDR R0,= 0x0804c088
该指令将值( 0x0804c088
)的寄存器 R0
。当我尝试访问该地址被存储在使用 X / X $ R0
使用 GDB
。我得到的消息:无法访问地址的内存
0x0804c088
。但是,这并不是地址,它是存储在寄存器中的值,该地址是存储在文字池 PC
相对地址。
什么是错误,我在那里做什么?我才明白了什么不对劲的地方?
此外,我应该如何设置文字池,你能举个例子吗?
@Carl Norum时:这里是code
__ __ ASM(LDR R0,= 0x0804c088);
__asm __(LDR R1,[PC,#34];);
Ø从GDB / P
(GDB)信息寄存器
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< test46 + 34>
CPSR 0x60000030 1610612784
(GDB)X / X $ R0
0x804c088:地址0x804c088不能访问存储器
(GDB)P / X $ R0
$ 1 = 0x804c088
(GDB)P / X $ R1
$ 2 = 0xf2c00300
(GDB)X / X $ R1
0xf2c00300:地址0xf2c00300不能访问存储器
(GDB)X / X $ R15
0x8a62&所述; test46 + 34计算值:0x1022f8df
gdb的 X
命令具有内在的取消引用操作。如果你想打印在值 R0
,只需要使用 P
:
P / X $ R0
你使用LDR
的形式是不是真正的指令 - 这是一个汇编程序宏指令是被转换成PC相对 LDR
指令和内存中的文字值某处(可能接近你使用它的位置)。如果你想找到的文字池常数的地址,你需要查看输出二进制文件。您的源装配code不包含它。
例如,让我们这个简单的例子程序:
.globl˚F
F:
LDR R0,= 0x12345678的
然后建立和拆解:
$臂无 - EABI - 铛-c example.s
$臂无 - EABI-objdump的-d example.oexample.o:文件格式ELF32-littlearm
.text段拆卸:00000000 LT; F&GT ;:
0:e51f0004 LDR R0,[PC,#-4] 4℃; F +为0x4>
4:12345678 .word为0x12345678
您可以看到文字是正好遇上偏移 4
。
您不需要做任何设置文字池。任何必要的文字将被汇编器为你设置。
I know how to load an immediate value using the LDR instruction in ARM.
For example:
LDR R0,=0x0804c088
This instruction loads the value (0x0804c088
) to the register r0
. When I try to access the address it is stored in using x/x $r0
using gdb
. I get the message: Cannot access memory at address
0x0804c088. But that is not the address, it is the value stored in that register and the address is a
PC
relative address which is stored in the literal pool.
What is the mistake that I doing there? did I understand something wrong there?
Moreover, How should I set the literal pool, can you give me an example please?
@Carl Norum: Here is the code.
__asm__("LDR R0,=0x0804c088");
__asm__("LDR R1,[PC, #34];");
O/p from gdb
(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 <test46+34>
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 <test46+34>: 0x1022f8df
The gdb x
command has an inherent dereferencing operation. If you want to print the value in r0
, just use p
:
p/x $r0
The form of LDR
you're using isn't a real instruction - it's an assembler macro-instruction that gets converted into a pc-relative ldr
instruction and a literal value someplace in memory (probably close to the location you're using it). If you want to find the address of the constant in the literal pool, you need to look at the output binary. Your source assembly code doesn't contain it.
For example, let's take this simple example program:
.globl f
f:
ldr r0,=0x12345678
And then build and disassemble it:
$ 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 <f>:
0: e51f0004 ldr r0, [pc, #-4] ; 4 <f+0x4>
4: 12345678 .word 0x12345678
You can see the literal is right there at offset 4
.
You don't need to do anything to "set up the literal pool". Any necessary literals will be set up for you by the assembler.
这篇关于LDR - 文字池 - ARM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!