目录

1、处理器模式

1.1、特权等级

1.2、处理器模式

2、寄存器组织

2.1、通用寄存器

2.2、特殊寄存器

3、指令集

3.1、指令集格式

3.2、常用指令集

3.2.1、LDR/STR

3.2.2、LDM/STM

3.2.3、MRS/MSR


ARM 官方针对 ARMv7-A 处理器的描述再:

ARMv7-A_and_R_Architecture_Reference_Manual

1、处理器模式

1.1、特权等级

ARMv7架构支持安全扩展,如果使能了安全扩展,ARMv7-A架构分为安全模式(Secure State)和非安全模式(Non-secure State)两个世界。
在非安全模式下,存在三种运行特权 PL0,PL1和 PL2(Privilege level)。(这里仅仅讨论非安全 State)

特权等级 描述
PL0 PL0运行在用户模式(User),用于运行应用程序。该模式程序受限访问系统资源。对应Linux用户态。
PL1 PL1运行非用户模式和Hyp模式外的所有模式。Linux内核运行在PL1。包含了ARMv6架构中的System,SVC,FIQ,IRQ,UNDEF及Abort模式。此外,安全模式中的Montior也运行在PL1等级,管理安全模式和非安全模式的切换。
PL2 PL2用于虚拟化。虚拟化超级管理程序(Hypervisor)运行在 PL2。

这里的 PL0~PL2 指的是特权等级,不同的特权等级,访问资源的权限不一样,操作系统运行再 PL1 的特权等级下,具有较高的访问权限,用户态运行再 PL0 的特权等级下(也叫非特权等级),只有最最基本的访问权限;

1.2、处理器模式

上面说的是处理器的特权等级,那么处理器真正的运行的模式有几种呢?如下所示:

可以看到,ARMv7-A 的处理器模式有 User、FIQ、IRQ、Supervisor、Monitor、Abort、Hyp、Undefined、System 模式:

User:用户模式,运行再 PL0 这个特权等级上,也就是没有特权等级,他是OS上运行应用程序时候的等级,他不可以访问系统资源(诸如 MMU 等),在这个模式下,无法主动切换模式,除非遇到中断或者异常(诸如 SWI 触发系统调用);

FIQ:快中断模式,发生 FIQ 快中断的时候处理器模式;

IRQ:中断模式,发生 IRQ 快中断的时候处理器模式;

Supervisor:管理员模式,复位后的默认模式,运行再 PL1 特权等级,可以通过 SWI(SVC) 系统调用呼叫产生 Supervisor Call 异常,进入 Supervisor 模式,操作系统常用的模式;

Monitor:监视模式,针对 Security 扩展,不详细讨论;

Abort:停止模式,当发生 Data Abort exception 或者 Prefetch Abort exception 异常时候进入这个模式;

Hyp:当支持虚拟化扩展的时候模式,不详细讨论;

Undefined:这是执行和指令相关的模式,当企图执行 UNDEFINED 指令的时候进入这个模式;

System:系统模式,也是 PL1 特权等级,和 Supervisor 的区别是,System 模式具有和 User 模式一样的寄存器,目前大多数系统未使用;

2、寄存器组织

2.1、通用寄存器

ARMv7-A 处理器有 16 个通用寄存器:R0~R15,其中:

R13:通常用做堆栈指针 SP;

R14:通常用作链接寄存器 LR;

R15:通常用作程序计数器 PC;

前面说了处理器有特权等级,每种特权等级访问系统资源的权限不一样,而处理器又有几种模式,每种模式对应的特权等级有一定区别;

每一种处理器模式对应的寄存器也有一定区别:

从上图可以看出:

1、R0~R7,PC是所有模式下共享的;

2、FIQ 模式下,R8~R12、SP、LR 都是有专门的寄存器,有的材料上,称之为“影子寄存器”,什么意思呢?这个模式下,有他专用的 R8~R12、SP、LR;

3、同样道理,Supervisor、Abort、Undefined、IRQ 等,都有他们自己模式下专用的 SP 和 LR,也就是说,从其他模式进来的时候,不需要针对这两个寄存器进行恢复现场;

4、FIQ 之所以称之为 FIQ,从软件上也看得出来,他专用的寄存器要多于 IRQ 的,所以也的确是要 Fast 一些;

从这里,我们也可以看出,exception 发生的时候,我们其实是有必要手动保存一些现场的;

2.2、特殊寄存器

ARMv7-A 还有一个特殊寄存器叫:程序状态寄存器 CPSR(Current Program Status Register),再进入异常之前,当前的 CPSR 被保存到 SPSR (Saved Program Status Register)中;

当然 CPRS 再用户层叫做 APSR,APSR 只是 CPSR 寄存器中被截取的一部分,因为在用户层,并不是所有的 CPSR 的位都可以访问;

CPSR 的组成如下所示:

Field 作用
N ALU返回运算结果是否为负数
Z ALU返回运算结果是否为0
C ALU运算是否发生进位
V ALU运算是否发生溢出
Q cumulative saturation
J ARM是否处于 Jazelle 状态
E 控制 load/store 字节序,E=1表示大端模式,E=0表示小端模式;
A disables asynchronous aborts,User模式不能操作
I 使能/禁能 IRQ,User模式不能操作,I=1表示禁止 IRQ,I=0表示使能 IRQ;
F 使能/禁能 FIQ,User模式不能操作,F=1表示禁止 FIQ,I=0表示使能 FIQ;
T ARM和Thumb状态标志位
GE 用于某些SIMD(Single Instruction, Multiple Data)指令
M[4:0] 处理器模式:FIQ,IRQ,ABT,SVC,UND,MON,HYP。User模式不能操作
IT[7:0] IT[7:2](bit15:10):和IT[1:0](bit26:25)一起组成IT[7:0],表示IF-THEN指令的执行状态;

这里的 M[4:0] 就是直接对应到了前面讲到的模式,还记得在前面那个处理器模式的列表中,每一个模式都对应了一个 Encoding 吗?这个 Encoding 就是这个 M 位的值;

3、指令集

ARMv7-A 支持 32bit ARM 指令集的同时,还支持 16bit 的 Thumb 指令集,它具有更好的代码密度,处理器可以在这两种指令集之间切换;

所有的Cortex-A系列处理器实现了Thumb-2技术,它扩展了Thumb指令集。混合使用32位和16位指令,以Thumb指令集的代码密度和接近ARM指令集的性能。自从所有的Cortex-A系列处理器支持这一扩展,针对它们的软件常被编译成Thumb指令集;

ARM 处理是加载/存储体系结构的典型的RISC处理器,对存储器的访问只能使用加载和存储指令实现。ARM 的加载/存储指令是可以实现字、半字、无符/有符字节操作;批量加载/存储指令可实现一条指令加载/存储多个寄存器的内容,大大提高效率;

3.1、指令集格式

基本格式为:

<opcode>{<cond>}{S} <Rd>,<Rn>{,<opcode2>}

<>内的项是必须的,{}内的项是可选的,如<opcode>是指令助记符,是必须的,而{<cond>}为指令执行条件,是可选的,如果不写则使用默认条件AL(无条件执行)

opcode:指令助记符,如 LDR,STR 等

cond:执行条件,如EQ,NE 等

S:是否影响CPSR 寄存器的值,书写时影响CPSR,否则不影响

Rd :目标寄存器

Rn:第一个操作数的寄存器

operand2:第二个操作数

3.2、常用指令集

3.2.1、LDR/STR

LDR指令用于从内存中读取数据放入寄存器中;STR 指令用于将寄存器中的数据保存到内存。指令格式如下:

LDR{cond}{T} Rd,<地址>;      加载指定地址上的数据(字),放入Rd中

STR{cond}{T} Rd,<地址>;      存储数据(字)到指定地址的存储单元,要存储的数据在Rd中

LDR/STR 指令寻址是非常灵活的,由两部分组成,一部分为一个基址寄存器,可以为任一个通用寄存器,另一部分为一个地址偏移量。地址偏移量有以下3种格式:

(1) 立即数。立即数可以是一个无符号数值,这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。指令举例如下:

LDR R0,=0X123     ; 将0X123存入r0中
LDR R0,=label     ; 将label_1所指向的地址值存入r0中LDR R1,[R0]       ; 将 R0      地址处的数据读出,保存到R1中 (R0 的值不变)
LDR R1,[R0,#0x12] ; 将 R0+0x12 地址处的数据读出,保存到R1中 (R0 的值不变)
LDR R1,[R0,#-0x12]; 将 R0-0x12 地址处的数据读出,保存到R1中 (R0 的值不变)

(2)寄存器。寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。指令举例值。指令举例如下:

LDR R1,[R0,R2]  ;   将R0+R2 地址的数据计读出,保存到R1中(R0 的值不变)
LDR R1,[R0,-R2] ;   将R0-R2 地址的数据计读出,保存到R1中(R0 的值不变)

(3)寄存器及移位常数。寄存器移位后的值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。指令举例如下:

LDR R1,[R0,R2,LSL #2] ;将R0+R2*4地址处的数据读出,保存到R1中(R0,R2的值不变)
LDR R1,[R0,-R2,LSL #2];将R0-R2*4地址处的数据计读出,保存到R1中(R0,R2的值不变)

一组代码示例:

NumCount EQU 0x40003000 ;定义变量NumCount
…
LDR R0,=NumCount ;使用LDR 伪指令装载NumCount的地址到R0
LDR R1,[R0] ;取出变量值
ADD R1,R1,#1 ;NumCount=NumCount+1
STR R1,[R0] ;保存变量值
…
GPIO 设置
GPIO-BASE EQU 0Xe0028000 ;定义GPIO 寄存器的基地址
…
LDR R0,=GPIO-BASE
LDR R1,=0x00FFFF00 ;装载32 位立即数,即设置值
STR R1,[R0,#0x0C] ;IODIR=0x00FFFF00, IODIR 的地址为0xE002800C
MOV R1,#0x00F00000
STR R1,[R0,#0x04] ;IOSET=0x00F00000,IOSET 的地址为0xE0028004

3.2.2、LDM/STM

批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM 为加载多个寄存器,STM 为存储多个寄存器。允许一条指令传送16 个寄存器的任何子集或所有寄存器。指令格式如下:

LDM{cond}<模式> Rn{!},reglist{^}

STM{cond}<模式> Rn{!},reglist{^}

LDM /STM 的主要用途是现场保护、数据复制、参数传送等。其模式有8种,如下所列:(前面4 种用于数据块的传输,后面4 种是堆栈操作)。

(1) IA:每次传送后地址加4
(2) IB:每次传送前地址加4
(3) DA:每次传送后地址减4
(4) DB:每次传送前地址减4
(5) FD:满递减堆栈
(6) ED:空递增堆栈
(7) FA:满递增堆栈
(8) EA:空递增堆栈

其中,寄存器Rn 为基址寄存器,装有传送数据的初始地址,Rn 不允许为R15;后缀“!”表示最后的地址写回到Rn中;寄存器列表reglist 可包含多于一个寄存器或寄存器范围,使用“,”分开,如{R1,R2,R6-R9},寄存器排列由小到大排列;“^”后缀不允许在用户模式呈系统模式下使用,若在LDM 指令用寄存器列表中包含有PC 时使用,那么除了正常的多寄存器传送外,将SPSR 拷贝到CPSR 中,这可用于异常处理返回;使用“^”后缀进行数据传送且寄存器列表不包含PC时,加载/存储的是用户模式的寄存器,而不是当前模式的寄存器。
地址对准――这些指令忽略地址的位[1:0]。
批量加载/存储指令举例如下:

LDMIA R0!,{R3-R9} ;加载R0 指向的地址上的多字数据,保存到R3~R9中,R0 值更新
STMIA R1!,{R3-R9} ;将R3~R9 的数据存储到R1 指向的地址上,R1值更新
STMFD SP!,{R0-R7,LR} ;现场保存,将R0~R7、LR入栈
LDMFD SP!,{R0-R7,PC}^;恢复现场,异常处理返回

在进行数据复制时,先设置好源数据指针,然后使用块拷贝寻址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB 进行读取和存储。而进行堆栈操作时,则要先设置堆栈指针,一般使用SP 然后使用堆栈寻址指令STMFD/LDMFD、STMED。LDMED、STMFA/LDMFA、STMEA/LDMEA实现堆栈操作。
使用LDM/STM 进行数据复制例程如下:

…
LDR R0,=SrcData ;设置源数据地址
LDR R1,=DstData ;设置目标地址
LDMIA R0,{R2-R9} ;加载8 字数据到寄存器R2~R9
STMIA R1,{R2-R9} ;存储寄存器R2~R9 到目标地址使用LDM/STM 进行现场寄存器保护,常在子程序中或异常处理使用:
SENDBYTE
STMFD SP!,{R0-R7,LR} ;寄存器入堆
…
BL DELAY ;调用DELAY 子程序
…
LDMFD SP!,{R0-R7,PC} ;恢复寄存器,并返回

值得注意的是一些诸如原子操作的指令:STREX/LDREX;

3.2.3、MRS/MSR

特殊寄存器 CPSR 通过 MRS 和 MSR 指令进行读写操作:

MRS:读状态寄存器指令。在ARM 处理器中,只有 MRS 指令可以状态寄存器CPSR或SPSR读出到通用寄存器中。

MRS{cond} Rd ,psr

Rd 目标寄存器。Rd 不允许为R15

举例:

MRS R1,CPSR     ;将CPSR状态寄存器读取,保存到R1 中
MRS R2,SPSR     ;将SPSR状态寄存器读取,保存到R2 中

MRS 指令读取CPSR,可用来判断ALU 的状态标志,或IRQ、FIQ中断是否允许等;在异常处理程序中,读SPSR 可知道进行异常前的处理器状态等。MRS 与MSR 配合使用,实现CPSR 或SPSR 寄存器的读—修改---写操作,可用来进行处理器模式切换(),允许/禁止IRQ/FIQ中断等设置。另外,进程切换或允许异常中断嵌套时,也需要使用MRS 指令读取SPSR 状态值。保存起来

举例:

使能IRQ 中断例程:
ENABLE_IRQ
MRS R0,CPSR
BIC R0,R0,#0x80
MSR CPSR_c,R0
MOV PC,LR禁能IRQ 中断例程:
DISABLE_IRQ
MRS R0,CPSR
ORR R0,R0,#0x80
MSR CPSR_c,R0
MOV PC,LR

MSR:写状态寄存器指令。在ARM 处理器中。只有MSR 指令可以直接设置状态寄存器CPSR或SPSR。指令格式如下:

MSR{cond} psr_fields,#immed_8r

MSR{cond} psr_fields,Rm

psr CPSR 或 SPSR,

fields 指定传送的区域。Fields 可以是以下的一种或多种(字母必须为小写):

c 控制域屏蔽字节(psr[7…0])
x 扩展域屏蔽字节(psr[15…8])
s 状态域屏蔽字节(psr[23。…16])
f 标志域屏蔽字节(psr[31…24])
immed_8r 要传送到状态寄存器指定域的立即数,8 位。
Rm 要传送到状态寄存器指定域的数据的源寄存器。

MSR 指令举例如下:

MSR CPSR_c,#0xD3 ;CPSR[7…0]=0xD3,即切换到管理模式。
MSR CPSR_cxsf,R3 ;CPSR=R3

注意:只有在特权模式下才能修改状态寄存器!

程序中不能通过MSR 指令直接修改CPSR 中的 T 控制位来实现ARM 状态/Thumb状态的切换,必须使用 BX 指令完成处理器状态的切换(因为BX 指令属转移指令,它会打断流水线状态,实现处理器状态切换)。MRS 与MSR 配合使用,实现CPSR或SPSR 寄存器的读-修改-写操作,可用来进行处理器模式切换、允许/禁止IRQ/FIQ 中断等设置。

堆栈指令实始化例程:
INITSTACK
MOV R0,LR ;保存返回地址
;设置管理模式堆栈
MSR CPSR_c,#0xD3
LDR SP,StackSvc
;设置中断模式堆栈
MSR CPSR_c,#0xD2
LDR SP,StackIrq

更多指令集 相关的详细内容,参考 ARM 官方文档,或者:

https://blog.csdn.net/u014069939/article/details/81107340

更多关于协处理器 Cp15 以及 Cache 和 MMU 相关的,在下一章介绍;

ARMv7-A 处理器窥探(1) —— 处理器模式相关推荐

  1. 【转】第8章 前摄器(Proactor):用于为异步事件多路分离和分派处理器的对象行为模式...

    目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...

  2. [css] 你知道css的预处理器和后处理器都有哪些吗?它们有什么区别呢?

    [css] 你知道css的预处理器和后处理器都有哪些吗?它们有什么区别呢? 目前最主流的 CSS 预处理器:Sass.LESS.Stylus .优缺点优点:语言级逻辑处理,动态特性,改善项目结构缺点: ...

  3. springMVC异常处理器:自定义异常处理器捕获系统异常,控制异常页面跳转

    首先看一个异常页面 404/500可能是大家最熟悉的两个错误代码,在传统方式下,代码遇到类如1/0这样的异常时,我们可以用try-catch捕获,交给前端控制器处理,如果前端控制器没有规范好异常处理器 ...

  4. java 笔记本i7 i5_笔记本i5处理器和i7处理器哪个好

    购买 笔记本电脑 的时候,运用什么处理器是消费者关注的焦点,处理器也是决定笔记本电脑价格多少的关键,也对性能有直接的影响.目前在笔记本电脑市场上,i5处理器和i7处理器都是主流的处理器类型,80%的笔 ...

  5. 计算机专业电脑i5与i7的区别,电脑i5处理器和i7处理器有什么区别

    各位朋友平时在购买电脑的时候,相信最看重的电脑参数就是CPU了,不过很多朋友也只是听说过CPU这个名词,在购买的时候也不知道具体应该怎样选择,尤其是在面对不同CPU产品的时候就更加难以选择了,只了解新 ...

  6. 从零开始设计RISC-V处理器——单周期处理器的设计

    系列文章目录 (一)从零开始设计RISC-V处理器--指令系统 (二)从零开始设计RISC-V处理器--单周期处理器的设计 (三)从零开始设计RISC-V处理器--单周期处理器的仿真 (四)从零开始设 ...

  7. 同构处理器和异构处理器的区别

    多核处理器 由于半导体工艺的极限限制,继续制造高性能的单核处理器将不再现实,并且随之带来的功耗与散热问题也没有解决方案.在这种情况下,越来越多的半导体厂商倾向于制造功耗更低.性能均衡的多核处理器以提高 ...

  8. 密码学博士必须掌握的52个知识点(二):多核处理器和矢量处理器之间的不同

      原文链接:http://bristolcrypto.blogspot.com/2014/10/52-things-number-2-what-is-difference.html   在一开始,你 ...

  9. 高通骁龙处理器,海思麒麟处理器以及联发科处理器 解说

    转载自百家号作者:数码玩伽 说到手机芯片,我们可以想到的无非就是高通骁龙处理器,海思麒麟处理器以及联发科处理器,虽然说苹果的A系列处理器目前还是最强,但是由于不是安卓系统的,所以我们也不予对比,今天我 ...

最新文章

  1. 2021年大数据Spark(十六):Spark Core的RDD算子练习
  2. python3.7怎么安装dlib_python3.7添加dlib模块的方法
  3. CentOS关机大法之shutdown应用实例
  4. iphone中怎么强制view重绘
  5. 装饰器模式(Decorator Pattern)
  6. nginx反向代理解决跨域问题,使本地调试更方便
  7. 自定义Stack接口
  8. 「雕爷学编程」Arduino动手做(32)——雨滴传感器模块
  9. 常用大部分渗透工具下载
  10. 分组求和并排序python_python 实现分组求和与分组累加求和代码
  11. 有没有好的公文写作范文素材,求助各位网友?
  12. [ALAPI]免费聚合视频无水印接口分享
  13. 5.2.3 UE behaviour in state 5GMM-REGISTERED
  14. oracle 取农历函数,完善SQL农历转换函数
  15. 3月18日短线黑马牛股公开验证
  16. PTA L1-039 python实现
  17. 小红书算法sign php,小红书API签名算法分析
  18. 十年经验的软件测试P7总监 给转行自动化软件测试六条学习建议
  19. 通过思维导图学习知识的两种模板鉴赏
  20. SOHO中国高管建“老鼠仓”吸钱 大企成空壳谁之责?

热门文章

  1. IT新闻类上榜100家最受欢迎博客网站
  2. 从一则IT新闻想到的
  3. selinux中Enforcing, Permissive 和Disable这三种模式的区别
  4. JuMP: 用Julia进行优化建模及求解- 覃含章的文章 - 知乎 https://zhuanlan.zhihu.com/p/40807662
  5. 【机械动力学】第一次在线作业
  6. 「西门子1847专家天团专访纪录片」始于1847,专家天团如何炼成
  7. ERROR conda.core.link:_execute(701);script output stdout:stderr: ‘chcp‘ ... return code: 1
  8. vivo AI计算平台 Kubernetes集群Ingress网关实践
  9. html5动态效果随鼠标动,html5跟随鼠标移动银河星系背景动画特效
  10. 重学 Java 设计模式:实战命令模式「模拟高档餐厅八大菜系,小二点单厨师烹饪场景」