一切的体系引导程序前面中会有一段相似的代码,如下:
.globl _start
_start: b
从中咱们可以看出,ARM支撑7种反常。问题时产生了反常后ARM是怎么呼应的呢?榜首个复位反常很好
了解,它放在0x0的方位,一上电就碑文它,并且咱们的程序总是从复位反常处理程序开端碑文的,因
此复位反常处理程序不需要回来。那么怎么会碑文到后边几个反常处理函数呢?
看看书后,了解了ARM对反常的呼应进程,于是就可以答复曾经的这个疑问。
当一个反常呈现今后,ARM会主动碑文以下几个过程:
(1)把下一条指令的地址放到衔接寄存器LR(通常是R14),这样就可以在处理反常回来时从正确的方位
持续碑文。
(2)将相应的CPSR(当时程序状况寄存器)复制到SPSR(备份的程序状况寄存器)中。从反常退出的时
候,就可以由SPSR来康复CPSR。
(3) 依据反常类型,强制设置CPSR的运转形式位。
(4)强制PC(程序计数器)从相关反常向量地址取出下一条指令碑文,然后跳转到相应的反常处理程
序中。
至于这些反常类型各代表什么,我也没有深究。由于往常就关怀reset了,也没有必要弄清楚。
ARM规则了反常向量的地址:
ldr pc, _undefined_instruction ;未定义的指令反常 0x4
这样了解这段代码就十分简略了。碰到反常时,PC会被强制设置为对应的反常向量,然后跳转到相应的
处理程序,然后再回来到主程序持续碑文。
这些引导程序的中止向量,是仅供引导程序自己运用的,一旦引导程序引导Linux内核结束后,会运用
自己的中止向量。
嗬嗬,这又有问题了。比方,ARM产生中止(irq)的时分,总是会跑到0x18上碑文啊。那Linux内核又怎
么能运用自己的中止向量呢?原因在于Linux内核选用页式存储办理。注册MMU的页面映射今后,CPU所
宣布的地址便是虚拟地址而不是物理地址。就Linux内核而言,虚拟地址0x18通过映射今后的物理地址
便是0xc000 0018。所以Linux把中止向量放到0xc000 0018就可以了。
MMU的两个首要效果:
(1)安全性:规则拜访权限
(2) 供给地址空间:把不接连的空间转换成接连的。
第2点是不是完成页式存储的意思?
.globl _start ;体系复位方位
_start: b reset ;各个反常向量对应的跳转代码
ldr pc, _undefined_instruction ;未定义的指令反常
……
_undefined_instruction :
.word undefined_instruction
惹祸有人会有疑问,同样是跳转指令,为什么榜首句用的是 b reset;
然后边的几个都是用ldr?
为了了解这个问题,咱们以未定义的指令反常为例。
当产生了这个反常后,CPU总是跳转到0x4,这个地址是虚拟地址,它映射到哪个物理地址
取决于详细的映射。
ldr pc, _undefined_instruction
相对寻址,跳转到标号_undefined_instruction,但是真实的跳转地址其实是_undefined_instruction
的内容——undefined_instruction。那句.word的相当于:
_undefined_instruction dw undefined_instruction (详见毕设笔记3)。
这个地址undefined_instruction到底有多远就难说了,惹祸和标号_undefined_instruction在同一个
页面,惹祸在很远的当地。不过除了reset,其他的反常是MMU开端作业之后才可能产生的,因而
undefined_instruction 的地址也通过了MMU的映射。
在刚加电的时分,CPU从0x0开端碑文,MMU还没有开端作业,此刻的虚拟地址和物理地址相同;另一方
面,重启在MMU开端作业后也有可能产生,假如reset也用ldr就有问题了,由于这时分虚拟地址和物理
地址彻底不同。
因而,之所以reset用b,便是由于reset在MMU树立前后都有可能产生,而其他的反常只要在MMU树立之
后才会产生。用b reset,reset子程序与reset向量在同一页面,这样就不会有问题(b是相对跳转的)
。假如二者相距太远,那么编译器会报错的