我正在尝试将ARM
注册(R0)
指向的数据加载到另一个注册(R1)
所以,我正在使用LDR R1,[R0]
。
但R0
是一个直接的价值
LDR R0,=0x0804c000
我遇到了分段错误。
注册信息
(gdb) info registers
r0 0x804c000 134529024
r1 0x1 1
r2 0x804c044 134529092
r3 0x1 1
r4 0x804c088 134529160
r5 0x0 0
r6 0x804c0cc 134529228
r7 0xbe9746c4 3197585092
r8 0x804c110 134529296
r9 0x8fb9 36793
r10 0x804c154 134529364
r11 0x0 0
r12 0x0 0
sp 0xbe9746c4 0xbe9746c4
lr 0x8939 35129
pc 0x89f0 0x89f0 <test46+48>
cpsr 0x60000030 1610612784
Disassembler:
(gdb) disassemble
Dump of assembler code for function test46:
0x000089c0 <+0>: push {r7}
0x000089c2 <+2>: add r7, sp, #0
0x000089c4 <+4>: ldr r0, [pc, #60] ; (0x8a04)
0x000089c6 <+6>: ldr r2, [pc, #64] ; (0x8a08)
0x000089c8 <+8>: ldr r4, [pc, #64] ; (0x8a0c)
0x000089ca <+10>: ldr r6, [pc, #68] ; (0x8a10)
0x000089cc <+12>: ldr.w r8, [pc, #68] ; 0x8a14
0x000089d0 <+16>: ldr.w r10, [pc, #68] ; 0x8a18
0x000089d4 <+20>: nop
0x000089d6 <+22>: nop
0x000089d8 <+24>: nop
0x000089da <+26>: nop
0x000089dc <+28>: nop
0x000089de <+30>: nop
0x000089e0 <+32>: nop
0x000089e2 <+34>: nop
0x000089e4 <+36>: nop
0x000089e6 <+38>: nop
0x000089e8 <+40>: nop
0x000089ea <+42>: nop
0x000089ec <+44>: nop
0x000089ee <+46>: nop
=> 0x000089f0 <+48>: ldr r1, [r0, #0]
0x000089f2 <+50>: ldr r3, [r2, #0]
0x000089f4 <+52>: ldr r5, [r4, #0]
0x000089f6 <+54>: ldr r7, [r6, #0]
0x000089f8 <+56>: ldr.w r9, [r8]
0x000089fc <+60>: ldr.w r11, [r10]
0x00008a00 <+64>: b.n 0x89f0 <test46+48>
End of assembler dump.
不能像这样使用LDR指令吗?我可以使用以下命令MOV R1, R0
以下是我的compilation flags:
gcc -std=c99 -mthumb -march=armv7 -mthumb-interwork -static -ffunction-sections
答案 0 :(得分:3)
根据您在另一个回复中的一条评论判断,我认为您对缓存如何工作的看法是错误的。我不相信支持缓存的内存可以直接访问,并查看数据表,我会说我是对的。用于缓存的RAM通常非常快,如果您可以避免在尝试访问主内存时涉及的典型地址周期,则效果最佳。此外,内核不允许直接访问L1的内容,因为它可能会给系统带来很多麻烦,即使你只是阅读它而不是写它 - 想想另一个可以检查它的用户空间进程内容并可能从中删回密码或其他敏感数据。通常,您通过系统协处理器执行影响缓存的操作,您需要在ARM Architecture Manual for the Cortex-A15中阅读。
即使您可以直接访问它,您也忘记了涉及MMU和Linux。 Linux设置的虚拟内存空间与处理器的物理空间大不相同。在这种情况下,0x0804c000
未映射,因此您会遇到分段错误。
我怀疑这个问题只是编码错误。 FWIW,您提供的代码段看起来是正确的,除了您正在访问无效的内存位置。
答案 1 :(得分:1)
该指令LDR R1, [R0]
从R0
获取地址,并将该地址的32位整数加载到R1
。
如果R0
中的地址不是有效地址,则会出现分段错误。您应该在该指令上设置断点,并查看此时R0
中的内容。
(gdb) break *0x000089f0
(gdb) run
<program hits breakpoint>
(gdb) info registers
<read value from R0>
然后,您可以尝试使用调试器从该地址加载,看看它是否在那里工作:
(gdb) x/x $r0
如果调试器可以读取地址,则问题不是您想象的那样;形成另一个假设并测试它。