type
status
slug
date
summary
tags
category
password
icon
第二章:ARM处理器及系统结构
工作状态
注意:ARM和Thumb状态间的切换并不影响处理器模式或寄存器内容。
从一个ARM例程调用另一个Thumb例程时,内核必须切换状态,反之亦然。
运行模式
我列出一些重要的模式(详细版本)
除用户模式外的其它6种处理器模式称为特权模式(Privileged Modes)。在特权模式下,程序可以访问所有的系统资源,也可以任意的进行处理器模式切换。
只有在特权模式下才允许对当前程序状态寄存器(CPSR)的所有控制位直接进行读/写访问,而在非特权模式下只允许对CPSR的控制位进行间接访问(SWI方式)。
特权模式中除系统模式之外的其他5种模式又统称为异常模式。它们除了可以通过在特权下的程序切换进入外,也可以由特定的异常进入。其中管理模式也称为超级用户模式,是为操作系统提供软中断的特有模式。
用户模式和系统模式共用一个,每种异常模式都有专用的R13寄存器。它们通常指向各模式所对应的专用堆栈,也就是说ARM处理器允许用户程序有6个不同的堆栈空间。
ARM的异常中断
地址 | 异常类型 | 进入时的模式 | 进入时I的状态 | 进入时F的状态 |
0x0000 0000 | 复位 | 管理 | 禁止 | 禁止 |
0x0000 0004 | 未定义指令 | 未定义 | I | F |
0x0000 0008 | 软件中断(SWI) | 管理 | 禁止 | F |
0x0000 000C | 预取中止(指令) | 中止 | I | F |
0x0000 0010 | 数据中止 | 中止 | I | F |
0x0000 0014 | 保留 | 保留 | — | — |
0x0000 0018 | IRQ | 中断 | 禁止 | F |
0x0000 001C | FIQ | 快中断 | 禁止 | 禁止 |
最后将向量地址存入PC,实现跳转
中断:
快速中断:
(1)专门为快中断配置了较多的私有寄存器,从而可使中断服务程序有足够的寄存器来使用,而不必与被中断服务程序使用同一组寄存器,这样就免去了因寄存器冲突而必需的保护及恢复现场工作。
(2)ARM把FIQ的中断向量放在了中断(异常)向量表末尾 0X0000001C处,因此它后面没有其它中断向量,允许用户将中断服务程序直接放在这里。
未定义指令:
中止异常:
在处理中止的原因之后,不管处于哪种处理器操作状态(ARM状态或者Thumb状态),处理程序可以通过执行下面的指令返回:
SUBS PC, R14_abt, #4 ;在中止模式下,执行该指令返回
SUBS指令将R14的值减4写入PC,CPSR将自动从SPSR寄存器中恢复并重试被中止的指令。
在指令预取时,无法正确读出指令(比如指令地址错误),该指令被标记成有问题的指令,这时,流水线上该指令之前的指令继续执行,当执行到该被标记成有问题的指令时,处理器产生指令预取中止异常中断。指令预取异常是由当前执行的指令自身产生的,当产生中断时,是处于译码阶段,程序计数器PC的值指向当前产生异常指令后面的那条指令。
在处理中止的原因之后,不管处于哪种处理器操作状态(ARM状态或者Thumb状态),处理程序可以通过执行下面的指令返回:
SUBS PC, R14_abt, #8 ;在中止模式下,执行该指令返回
SUBS指令将R14的值减8写入PC(返回并重新执行导致异常的指令),CPSR将自动从SPSR寄存器中恢复并重试被中止的指令。
SWI处理程序通过执行下面的指令返回 :
MOVS PC, R14_svc ;在管理模式下,执行该指令返回
MOVS指令将R14的值写入PC,CPSR将自动从SPSR寄存器中恢复并返回到SWI指令之后的指令。
第三章:ARM指令集
ARM指令和条件码:
ARM 指令的 条件码 和 助记符 如下表所示:
条件码 | 条件码助记符 | CPSR中条件标志位值 | 含义 |
0000 | EQ | Z=1 | 相等 |
0001 | NE | Z=0 | 不相等 |
0010 | CS/HS | C=1 | 无符号数大于或等于 |
0011 | CC/LO | C=0 | 无符号数小于 |
0100 | MI | N=1 | 负数 |
0101 | PL | N=0 | 正数或零 |
0110 | VS | V=1 | 溢出 |
0111 | VC | V=0 | 未溢出 |
条件码 | 条件码助记符 | CPSR中条件标志位值 | 含义 |
1000 | HI | C=1且Z=0 | 无符号数大于 |
1001 | LS | C=0或Z=1 | 无符号数小于或等于 |
1010 | GE | N=V | 带符号数大于或等于 |
1011 | LT | N!=V | 带符号数小于 |
1100 | GT | Z=0且N=V | 带符号数大于 |
1101 | LE | Z=1或N!=V | 带符号数小于或等于 |
1110 | AL | ㅤ | 无条件执行 |
1111 | NV | ARMV3之前 | 从不执行(不要使用) |
(1)如果既有条件后缀又有S后缀,则书写时S排在后面
如:ADDEQS R1,R0,R2
该指令在Z=1时执行,将R0+R2的值放入R1,同时刷新条件标志位。
(2)条件后缀是要测试条件标志位,而S后缀是要刷新条件标志位。
(3)条件后缀要测试的是执行前的标志位,而S后缀是依据指令的结果改变条件标志。
ARM 指令可以分为:分支指令、数据处理指令、存储访问指令、协处理器指令和杂项指令五类。
分支指令
分支指令用于控制程序的执行流程、实现ARM代码与Thumb代码之间进行切换。
数据处理指令
数据处理指令在通用寄存器上执行计算,主要分为3种:算术/逻辑指令、比较指令和乘法指令。
存储访问指令
用于加载/存储存放于MCU片外存储系统中的数据。加载指令用于从内存中读取数据放入寄存器中,存储指令用于将寄存器中的数据保存到内存中。
ARM协处理器指令
ARM协处理器指令用于控制外部的协处理器。包括
数据处理指令:启动一个协处理器专用的内部操作。
数据转移指令:使数据在协处理器和存储器之间进行转移。
寄存器转移指令:协处理器值转移到ARM寄存器或ARM寄存器的值转移到协处理器。
杂项指令
包括状态寄存器转移指令和异常中断产生指令。
状态寄存器转移指令将CPSR或SPSR的内容转移到一个通用寄存器,或者反过来将通用寄存器的内容写入CPSR或SPSR寄存器
ARM有 两条 异常中断产生指令,分别为 软中断指令SWI 和 断点中断指令BKPT。
寻址方式
立即数寻址:
共有6种移位方式:
— LSL 逻辑左移 — LSR 逻辑右移
— ASL 算术左移 — ASR 算术右移
— ROR 循环右移 — RRX 带扩展的循环右移
变址寻址
多寄存器寻址
分支指令
B和BL的区别在于:BL在跳转之前会把BL指令的下一条指令地址(断点地址)保存到连接寄存器 LR(R14),因此程序在必要的时候可以通过将 LR 的内容加载到 PC 中,使程序返回到跳转点。
BL 指令经常被用来调用一个子程序。
signed_immed_24 间接提供目标地址,真正的目标地址是由处理器根据这个有符号数和当前的PC值计算出来的。
具体计算为:先将 signed_immed_24 左移两位(即具有26位的偏移量),并扩展为32位有符号数,然后再将这32位有符号数与 PC 的当前值相加,得到实际的跳转地址。
因此B 和 BL 指令转移的偏移量为 26 位,即转移的跨度为前后 32MB 地址空间。
另一种实现指令跳转的方式是通过直接向 PC 寄存器中写入目标地址值(并不是一定MOV写),实现在 4GB 地址空间中任意跳转,这种跳转又称为长跳转。
如果在长跳转指令之前使用“MOV LR,PC” 等指令,可以保存将来返回的地址值,也就实现了在 4GB 的地址空间中的子程序调用。
数据处理指令
加减法
ADC
SBC
RSB
RSC
乘法指令
存储器访问指令
LDR、LDRSB、LDRB、LDRSH、LDRH、STR、STRB、STRH
SWP
LDM STM
(1)Rn:表示基址寄存器,装有传送数据的初始地址,Rn不允许为R15(即PC)。
(2)Rn后缀“!”:表示最后的地址写回到Rn中。
(3)Reglist:表示寄存器列表,其中包含一个或多个寄存器。当寄存器不连续时,中间使用“,”隔开。
格式例子:{R1,R2,R6-R9}
列表寄存器和存储器地址的关系规则:编号低的寄存器对应于存储器中低地址单元,编号高的寄存器对应于存储器中高地址单元。
(4)后缀“^”说明
寄存器列表不包含PC:使用后缀“^”进行数据传送时,加载/存储的是用户模式的寄存器,而不是当前模式的寄存器。
寄存器列表包含有PC:除了正常的多寄存器传送外,还要将SPSR拷贝到CPSR中。该用法可用于异常处理返回。
禁用情况:后缀“^”不允许在用户模式或系统模式下使用。 因为它们没有SPSR
(5)当Rn在寄存器列表中且使用后缀“!”
对于STM指令,若Rn为寄存器列表中的最低序号的寄存器,则会将Rn的初值保存;
其它情况下Rn的编译无法通过。
(6)地址字对齐
这些指令寻址是字对齐的,即忽略地址位[1:0]。
逻辑运算
异或
杂项指令
MRS、MSR
MRS Move to Register from Special Register
moves the value from the selected special-purpose register into a general-purpose register.
MSR Move to Special Register from Register
moves the value from a general-purpose register into the selected special-purpose register .
SWI
参数传递通常有两种方法:
指令中的24bit立即数指定API号,其它参数通过寄存器传递。
忽略指令中的24bit立即数,r0指定API号,其它参数通过其它寄存器传递。
一、算数逻辑运算指令的应用
例1: 实现乘法的指令段
MOV R0,R0,LSL #n ;R0=R0<<n;R0= R02n
ADD R0,R0,R0,LSL #n ;R0=R0+R02n= R0*(2n+1)
RSB R0,R0,R0,LSL #n ;R0=R02n-R0= R0(2n-1)
两个64位数据的比较操作,并设置CPSR中的条件标志位。
CMP R1,R3 ;比较高32位
CMPEQ R0,R2 ;如果高32位相等,比较低32位
第四章:伪指令
全局变量 的变量名在整个程序范围内必须具有 唯一性。
局部变量 的变量名在变量作用范围内必须具有唯一性。
在默认情况下,局部变量只在定义该变量的程序段内有效。
汇编程序语言设计
C/C++语言和汇编语言的混合编程
内联汇编
嵌入式汇编
_ _asm return–type function–name(parameter-list)
{
汇编程序段
}
return–type:函数返回值类型,C语言中的数据类型;
function–name:函数名;
parameter-list:函数参数列表。
注:ADS环境中不能使用嵌入式汇编。
嵌入式汇编在形式上看起来就像使用关键字 _ _asm进行了声明的函数,如下所示: