分段故障 - ARM组装

时间:2013-07-04 09:02:25

标签: gcc assembly arm

我正在尝试将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

将数据从R0移动到R1而没有任何问题

以下是我的compilation flags:

gcc -std=c99 -mthumb -march=armv7 -mthumb-interwork -static -ffunction-sections

2 个答案:

答案 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

如果调试器可以读取地址,则问题不是您想象的那样;形成另一个假设并测试它。