首页 > 对ARM异常(Exceptions)的理解

对ARM异常(Exceptions)的理解

对ARM异常(Exceptions)的理解
1 .对 ARM 异常( Exceptions )的理解
所有的系统引导程序前面中会有一段类似的代码,如下:
.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                       ;快速中断异常
从中我们可以看出, ARM 支持 7 种异常。问题时发生了异常后 ARM 是如何响应的呢?第一个复位异常很好理解,它放在 0x0 的位置,一上电就执行它,而且我们的程序总是从复位异常处理程序开始执行的,因此复位异常处理程序不需要返回。那么怎么会执行到后面几个异常处理函数呢?
看看书后,明白了 ARM 对异常的响应过程,于是就能够回答以前的这个疑问。
当一个异常出现以后, ARM 会自动执行以下几个步骤:
1 )把下一条指令的地址放到连接寄存器 LR( 通常是 R14) ,这样就能够在处理异常返回时从正确的位置继续执行。
2 )将相应的 CPSR( 当前程序状态寄存器 ) 复制到 SPSR (备份的程序状态寄存器)中。从异常退出的时候,就可以由 SPSR 来恢复 CPSR
(3) 根据异常类型,强制设置 CPSR 的运行模式位。
4 )强制 PC (程序计数器)从相关异常向量地址取出下一条指令执行,从而跳转到相应的异常处理程序中。
至于这些异常类型各代表什么,我也没有深究。因为平常就关心 reset 了,也没有必要弄清楚。
ARM 规定了异常向量的地址:
   b       reset            ; 复位 0x0
ldr pc, _undefined_instruction ;未定义的指令异常 0x4
       ldr     pc, _software_interrupt     ;软件中断异常    0x8
       ldr     pc, _prefetch_abort          ;预取指令    0xc
       ldr     pc, _data_abort               ;数据        0x10
       ldr     pc, _not_used                  ;未使用      0x14
       ldr     pc, _irq                       ;慢速中断异常   0x18
        ldr   pc, _fiq                       ;快速中断异常    0x1c
这样理解这段代码就非常简单了。碰到异常时,PC会被强制设置为对应的异常向量,从而跳转到相应的处理程序,然后再返回到主程序继续执行。
这些引导程序的中断向量,是仅供引导程序自己使用的,一旦引导程序引导Linux内核完毕后,会使用自己的中断向量。
嗬嗬,这又有问题了。比如,ARM发生中断(irq)的时候,总是会跑到0x18上执行啊。那Linux内核又怎么能使用自己的中断向量呢?原因在于Linux内核采用页式存储管理。开通MMU的页面映射以后,CPU所发出的地址就是虚拟地址而不是物理地址 。就Linux内核而言,虚拟地址0x18经过映射以后的物理地址就是0xc000 0018。所以Linux把中断向量放到0xc000 0018就可以了。
另外,说一下MMU。说句实话,还不是很明白这个MMU机理。
  (1 )安全性:规定访问权限
 (2) 提供地址空间:把不连续的空间转换成连续的。
第2点是不是实现页式存储的意思?
2005 年6月9日
补充一下:  05/06/14



.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是相对跳转的)。如果二者相距太远,那么编译器会报错的。

更多相关:

  • org.apache.shiro.authc.pam.UnsupportedTokenException org.apache.shiro.authc.UnknownAccountExce...

  • 什么是异常处理 异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止),在python中,错误触发的异常如下 语法错误: 这种错误根本就过不了python解释器的语法检测,必须在程序执行前就改正逻辑错误:#TypeError:int类型不可迭代 for i in...

  • Ø  前言 本文主要记录 Android 的常见异常及解决办法,以备以后遇到相同问题时可以快速解决。   1.   java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.la...

  • Python之路【第五篇】:面向对象及相关 Python之路【第五篇】:面向对象及相关 面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇面向对象进阶篇其他相关 一、isinstance(obj, cls)  检查是否obj是否是类 cls 的对象 1 2 3 4 5 6 class Foo(o...

  • 51 三菱PLC可读不可写Q:MT8102IQ和三菱Q系列PLC通讯,屏无法写入PLC,但是可以读取PLC的状态和数值?A:PLC程序中"允许RUN中写入"打钩,程序下载重启后解决。52 控制不了输入点Q:触摸屏做了三菱PLC的X点的元件,但是控制不了X输出?A:是的,PLC端X点无法通过触摸屏控制输出,屏上只能做X点的显示。53 M...

  • 传统方法(仅适用于普通项目):   1、在vscode中安装 Live Server 插件: 2、安装成功后,vscode右下角会有 Go Live 标识点击: 3、cmd ipconfig 查询自己电脑的ip地址: 4、复制地址替换端口前的地址(http://127.0.0.1:8080修改为http://192.168....

  • ngx_http_geo_module模块,默认情况下,nginx会加载,除非人为的 --without-http_geo_module。 这个模块提供了一个非常好用的geo指令,可以用它来创建变量,诞生其值依赖于客户端IP地址。 ngx_http_geo_module 模块官网地址 http://nginx.org/en...

  • uboot启动Linux内核过程分为4大步骤: 问题2: uboot阶段DDR的分区的问题 上述步骤2和步骤4中,有将uboot/kernel拷贝纸DDR的步骤,具体要拷贝到DDR的什么位置呢? 分清楚这两个概念: 链接地址:链接时指定的地址(指定方式为:Makefile中用-Ttext,或者链接脚本) 运行地址:程序实际运行...

  • 在Linux系统中,以32bit x86系统来说,进程的4GB内存空间(虚拟地址空间)被划分成为两个部分 ------用户空间和内核空间,大小分别为0-3G,3-4G。        用户进程通常情况下,只能访问用户空间的虚拟地址,不能访问到内核空间。          每个进程的用户空间存放用户的程序和代码(堆栈,数据区,代码区等)...