下面的代码是用于定义中断向量表的u-boot的第一部分,我的问题是如何使用每一行。我理解前两行是起点和第一条实现的指令:reset,我们在下面定义reset。但我们什么时候会在下面使用这些说明?根据System.map,每条指令都有一个固定的地址,所以_fiq在0x0000001C,当我们想要执行fiq时,我们会将这个地址复制到pc然后执行,对吧?但是我们可以通过哪种方式跳转到这条指令:ldr pc,_fiq?它是通过硬件还是软件实现的?希望我能让自己理解正确。
>.globl _start
>_start:b reset
> ldr pc, _undefined_instruction
> ldr pc, _software_interrupt
> ldr pc, _prefetch_abort
> ldr pc, _data_abort
> ldr pc, _not_used
> ldr pc, _irq
> ldr pc, _fiq
>_undefined_instruction: .word undefined_instruction
>_software_interrupt: .word software_interrupt
>_prefetch_abort: .word prefetch_abort
>_data_abort: .word data_abort
>_not_used: .word not_used
>_irq: .word irq
>_fiq: .word fiq
答案 0 :(得分:10)
如果您了解重置,那么您就能理解所有这些。
当处理器复位时,硬件将pc设置为0x0000并通过获取0x0000处的指令开始执行。当执行未定义的指令或尝试执行时,硬件通过将pc设置为0x0004来响应并开始执行0x0004处的指令。 irq中断,硬件完成正在执行的指令开始执行地址0x0018的指令。等等。
00000000 <_start>:
0: ea00000d b 3c <reset>
4: e59ff014 ldr pc, [pc, #20] ; 20 <_undefined_instruction>
8: e59ff014 ldr pc, [pc, #20] ; 24 <_software_interrupt>
c: e59ff014 ldr pc, [pc, #20] ; 28 <_prefetch_abort>
10: e59ff014 ldr pc, [pc, #20] ; 2c <_data_abort>
14: e59ff014 ldr pc, [pc, #20] ; 30 <_not_used>
18: e59ff014 ldr pc, [pc, #20] ; 34 <_irq>
1c: e59ff014 ldr pc, [pc, #20] ; 38 <_fiq>
00000020 <_undefined_instruction>:
20: 00000000 andeq r0, r0, r0
00000024 <_software_interrupt>:
24: 00000000 andeq r0, r0, r0
00000028 <_prefetch_abort>:
28: 00000000 andeq r0, r0, r0
0000002c <_data_abort>:
2c: 00000000 andeq r0, r0, r0
00000030 <_not_used>:
30: 00000000 andeq r0, r0, r0
00000034 <_irq>:
34: 00000000 andeq r0, r0, r0
00000038 <_fiq>:
38: 00000000 andeq r0, r0, r0
当然,除了更改电脑和从这些地址开始执行之外。硬件将保存机器状态,必要时切换处理器模式,然后从向量表开始执行新地址。
我们作为程序员的工作是构建二进制文件,以便我们希望为每条指令运行的指令位于正确的地址。硬件为每个位置提供一个字,一条指令。现在,如果您从未期望过任何这些异常,那么您不必在地址零处有一个分支,例如您可以让您的程序启动,这些地址的内存没有任何魔力。如果您希望有这些例外,那么对于一个单词的指令有两种选择,并且可以跳出后面的异常。一个是分支,另一个是负载pc。各有利弊。
答案 1 :(得分:6)
当硬件发生异常时,程序计数器(PC)自动设置为相关异常向量的地址,处理器开始执行该地址的指令。当处理器复位时,PC会自动设置为base+0
。未定义的指令将PC设置为base+4
等。向量表(base
)的基址是0x00000000,0xFFFF0000或VBAR
,具体取决于处理器和配置。请注意,这在向量表放置的位置提供了有限的灵活性,您需要查阅ARM文档以及您正在使用的设备的参考手册以获得正确的值。
表的布局(每个异常4个字节)使得必须立即从向量分支到实际的异常处理程序。 LDR PC, label
方法的原因是双重的 - 因为使用B
将PC相对分支限制为(24 <2)位(+/- 32MB)将限制代码的布局在记忆中有点;通过加载绝对地址,处理程序可以位于内存中的任何位置。其次,通过简单地将不同的地址写入该位置,而不必组装和编写分支指令,可以非常简单地在运行时更改异常处理程序。
以这种方式拥有可重映射的复位向量几乎没有价值,但这就是为什么你倾向于看到一个实现为一个简单的分支,以跳过其余的向量到真正的入口点代码。