| |
arm寄存器
-------------------------------------------------------------
Author :tiger-john
WebSite :blog.csdn.net/tigerjb
Email :jibo.tiger@gmail.com
Update-Time : 2011年2月14日星期一
Tiger声明:本人鄙视直接复制本人文章而不加出处的个人或团体,
但不排斥别人转载tiger-john的文章,只是请您注明出处并和本人
联系或留言给我。3Q
-------------------------------------------------------------
在ARM处理器内部共有37个用户可访问的寄存器,分别为
31个通用的32位寄存器和6个状态寄存器。
一.通用寄存器:
1.在汇编语言中,寄存器R0-R13为保存数据或地址值的通用寄存器。
2.其中寄存器R0-R7为未分组的寄存器。
对于任何处理器模式,它们都共享R0~R7的通用寄存器。
3.寄存器R8-R12为两个分组的物理寄存器。
a.FIQ拥有自己独立的R8~R12的通用寄存器。
b.其他六种处理器模式共享R8~R12的通用寄存器
注:寄存器R8~R12在ARM体系结构中没有特定的用途。
给FIQ单独的R8~R12可实现快速的中断处理(在发生FIQ中断后,处理器不用为了保护寄存器而浪费时间,从而提高了FIQ的处理速度)
4.寄存器R13和R14
a. 用户模式和系统模式公用R13和R14的寄存器内容。
b. 其它五个模式拥有自己独立的R13和r14寄存器内容。
c. R13作为堆栈指针(SP),用于保存待使用的寄存器内容。
d. 寄存器R14称为链接寄存器(LR),它的作用有两个:
l 当使用BL指令调用子程序时,系统会自动将 BL指令的下一条指令的地址存入R14中。
Ø 程序A指令过程中调用程序B
Ø 程序跳转至标号Lable处,执行程序B.
Ø 系统将BL Lable指令的下一条指令所在地址存入R14中
Ø 程序B执行最后,执行语句MOV PC,LR将R14寄存器的内容放入PC处,返回至NEXT处继续执行。
l 当发生异常时,系统自动将异常的返回地址放入R14中(有些异常有一个小的固定的偏移量)
二.重要的寄存器
1.堆栈指针R13
R13作为堆栈指针SP。在ARM指令集中,由于没有以特殊方式使用R13的指令。(在Thumb)指令集中存在使用R13的指令)
每个异常模式都有其自身的R13分组版本,它通常指向由异常模式所专用的堆栈。在入口处,异常处理程序通常将其他要使用的寄存器值保存到这个堆栈。通过返回时将这些值重装到寄存器中。异常处理程序可确保异常发生时的程序状态不会被破坏。
2.链接寄存器R14
寄存器R14(也称为链接寄存器或LR)在结构上有两个特殊功能:
1>在每种模式下,模式自身的R14用于保存子程序返回地址。
a. 当使用BL或BLX指令调用子程序时,R14设置为子程序返回地址。
b. 子程序返回通过将R14复制到程序计数器来实现。(p41)
2>当发生异常时,将R14对应的异常模式设置为返回地址。异常返回的执行类似于子程序返回,只是使用稍微不同的指令来确保被异常中断的程序状态能够完全恢复。
3.程序计数器R15
1>R15里存放的是正在取值的指令。
而成都网络推广人们一般习惯的约定将“正在执行”的指令作为参考点,则:PC=当前程序执行位置+8
2>七种模式共用R15寄存器。
3>由于ARM指令总是以字节为单位,所以R15寄存器的最低两位总是为0。
注:
1. 当指令对R15的读取没有超过任何对R15使用的限制时,对R15读取的值是指令的地址加上8字节。
2. 用命令读取PC的方式主要用于对附近的数据进行快速,与位置无关的寻址,包括程序中与位置无关的移动。
3. 但是在使用STR或STM指令保存时,会出现两种情况:
A. 这些指令可将指令地址加8字节保存(和其它指令读取R15一样)
B. 这些指令或将指令自身地址加12字节。
这与具体的芯片有关。
由于这个原因,使用STR和STM指令是不可移植的。
因此,我们要避免使用STR和STM指令来保存R15.
4. 使用下面的程序可以看到这个具体的偏移量。
5. 写R15的一般限制:写如R15值的bit[1:0] 必须为0b00;如果不是,则结果将不可预测。
6. 大多数指令通过指令所指的偏移量与PC值相加并将结果写入PC来计算目标地址:
(当前指令的地址)+8+偏移量。
7. 正常连续执行的指令实际上是通过计算:
(当前指令的地址)+4
来计算下一条要执行的指令。
注:区别两个概念:
1. 跳转目标的计算方法:
(当前指令的地址)+8+偏移量
2. 下一条指令位置的计算方法:
(当前指令的地址)+4
三.当前程序状态寄存器
在ARM内核中包含1个CPSR和5个供异常处理程序使用的SPSR.
先来看图
1. CPSR(当前程序状态寄存器)
1>七中模式共享一个程序状态寄存器。
2>在进入异常模式中,另外一个寄存器程序状态保存寄存器SPSR可以被访问(系统和用户模式没有SPSR寄存器,其它五中模式都有其自己独立的SPSR寄存器)。在进入异常时,它保存CPSR的当前值;在异常退出时,可通过它恢复CPSR.
作用:反映当前处理器的状态,其包含:
a.4个条件标志位(负标志位N,零标志Z,近位标志位C和溢出标志位V)
b.2个中断禁止位,分别用于一种类型的中断。
c.5个对当前处理器模式进行编码的位
d.1个用于指示当前处理器状态的标志位(t)
John哥说明:
切记在修改寄存器中的值时,要采用读-修该-写的方式。
(首先读出目标寄存器中的数据,再对关心的比特进行修改,之后将准备好的数据写回到目标寄存器中。)
这样做的好处是:
1.不会改变原来不相关管脚的功能属性。
2.不会影响到寄存器中保留位的数据。
eg:PINSEL0 = (PINSEL0 & (~(3<<10)) |( 2<<10);
这时一种良好的写法,他实现了对P0.5端脚的修改(即对PINSEL0寄存器中的11:10位比特位进行修改,对于他实现的功能请查阅数据手册,这里不做解释)
尽量不要采用直接对寄存器写的操作,因为这样可能把寄存器中的所用值都修改了。那么它的后果,我想哥不说你也明白。
2. 条件代码标志:
N:当该位为1时:表示负数。为0时:表示正数。
Z:当该位为1时:表示两数相等。为0时:表示两数不相等。
C:当该为1时:若为加法运算(含CMN)表示产生进位,否则C=0;
当该位为1时:若为减法运算(含CMP)表示不借位,否则C=0(即产生借位)
注:对于移位运算C为最后的移出值,其他指令C通常不变。
V:当该位为1时:使用加法/减法运算时,表示有符号溢出。;否则V=0;
注:
在ARM中,所用指令都可按条件来执行。
在Thumb中,只有分支指令可条件执行。
3. 控制位:
CPSR的最低8位为控制位。分别是中断禁止位,T位,模位。
1> 当发生异常时,控制位改变。当处理器在一个特权模式下操作时,可用软件操作这些位。
a. 中断标志位:
当I位为1时,IRQ中断被禁止
当F位为1时,FIQ中断被禁止.
b. T位:
该位反映了处理器状态:
当T位为1时,处理器处于Thumb状态下运行。
当T位为0时,处理器处于ARM状态下运行。
John哥说明:
绝对不要强制改变CPRS寄存器中的T位,否则处理器会进入一个无法预测的状态,那么你也就杯具了。
2> 模式为
M4,M3,M2,M1