首页 > 其他分享 >ARMv7-A 处理器窥探(1) —— 处理器模式

ARMv7-A 处理器窥探(1) —— 处理器模式

时间:2023-05-13 17:24:22浏览次数:40  
标签:R0 R1 模式 窥探 指令 处理器 ARMv7 寄存器 CPSR

arm官方资料

ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition.pdf

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。包含了ARMv7架构中的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 的组成如下所示:

这里的 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

 

标签:R0,R1,模式,窥探,指令,处理器,ARMv7,寄存器,CPSR
From: https://www.cnblogs.com/god-of-death/p/17397735.html

相关文章

  • MT6739 芯片/处理器规格参数介绍 MTK6739核心板
    MT6739芯片采用了四核Cortex-A53的架构,搭配PowerVRGE8100GPU,整合支持最高1080p30fps的视频编解码器和4GCat-4LTE调制解调器以及高达8MP的摄像头,为智能终端提供了一种高效的解决方案。基于MT6739的智能手机配合400MHz的GPU时钟速度能够支持扎实的图像性能表现和出色的......
  • MT6761 芯片/处理器参数介绍 MTK6761 核心板
    MT6761是联发科推出的一款低功耗、高效能的中端移动处理器。它采用了四核Cortex-A53处理器和IMGGE8300GPU,与其它中端处理器相比,MT6761在CPU和GPU性能方面都有明显提升。在性能方面,MT6761的主频为2.0GHz,采用全新的12nm制程工艺,配备了4GBLPDDR3RAM,这使其处理速度得到了......
  • S5PV210 | 微处理器启动流程
    S5PV210|微处理器启动流程目录S5PV210|微处理器启动流程S5PV210启动概述S5PV210的启动顺序iROM(BL0)的启动顺序V210启动流程图第一次启动失败时的iROM第二次启动顺序用于引导代码描述的标题信息数据编写校验和示例代码S5PV210启动概述S5PV210支持从多种设备启动,如OneNAN......
  • 龙芯3a5000处理器下编译Qt源码
    1、下载Qt源码,archive/qt/5.12/5.12.8/single/qt-everywhere-src-5.12.8.tar.xz2、安装依赖库:sudoapt-getinstallflexsudoapt-getinstallbisonsudoapt-getinstallgperfsudoapt-getinstallbuild-essentialsudoapt-getinstalllibgl1-mesa-devsudoapt-getin......
  • 一站式统一返回值封装、异常处理、异常错误码解决方案—最强的Sping Boot接口优雅响应
    作者:京东物流 覃玉杰1.简介GracefulResponse是一个SpringBoot体系下的优雅响应处理器,提供一站式统一返回值封装、异常处理、异常错误码等功能。使用GracefulResponse进行web接口开发不仅可以节省大量的时间,还可以提高代码质量,使代码逻辑更清晰。强烈推荐你花3分钟学会它!......
  • 全新 – Amazon EC2 R6a 实例由第三代 AMD EPYC 处理器提供支持,适用于内存密集型工作
    我们在Amazonre:Invent2021上推出了通用型AmazonEC2 M6a实例,并于今年2月推出了计算密集型 C6a实例。这些实例由运行频率高达3.6GHz的第三代AMDEPYC处理器提供支持,与上一代实例相比,性价比提高多达35%。如今,我们正在扩展产品组合,添加内存优化型 AmazonEC2R6a......
  • 十二代酷睿处理器N100 N200 N305 等安装ESXI紫屏问题解决办法
    12代大小核紫屏报错解决方案四部曲1、安装界面倒计时结束之前,按SHIFT+O,在原有命令后面加空格后输入以下代码cpuUniformityHardCheckPanic=FALSE2、安装完ESXI之后会重启,在重启界面倒计时结束前,再操作一次,按住SHIFT+O,输入cpuUniformityHardCheckPanic=FALSE3、进入ESXI把SSH功能......
  • Hbase 协处理器 RegionObserver
     RegionObserver注:每次更新协处理器方法,最好加上版本更新,否则可能会出现更新失败协处理器安装-表级别安装disable'wechat_article'alter'wechat_article',METHOD=>'table_att','coprocessor'=>'hdfs://test111:8020/coprocessor/hbase-coprocessor-0.0.6-S......
  • Hbase 协处理器之将数据保存到es (二级索引)
    利用HbaseCoprocessor实现将插入hbase中的数据保存至ElasticSearch中,实现二级索引目的版本:Hbase:2.1ES:6.3.0一、Coprocessor代码开发协处理器类packagewiki.hadoop.coprocessor;importorg.apache.hadoop.hbase.Cell;importorg.apache.hadoop.hbase.CellUtil;importorg.ap......
  • double类型格式化处理器(保留两位小数)
    /***构造一个double类型格式化处理器*/DecimalFormatdf=newDecimalFormat(".00");//保留两位小数//例子:1/3=0.0Stringformat=df.format(1.0/3);//1.0/3=0.333333333333333333333333...//但是返回是一个shring类型的字符,所以需要用到double......