跟我一起学RT-Thread之ARM架构初探

1.地址空间

1.1.ARM架构下CPU如何访问寄存器

答案其实很简单:指针

int  a; 
unsigned int *p = &a;  // p等于“a的地址”

*p = val;  // 写这个地址,就是写a

val = *p;  // 读这个地址,就是读a

unsigned int *p = 0x40010800; // p等于某个寄存器的地址
*p = val;  // 写这个地址,也就是写这个寄存器
val = *p; // 读寄存器

1.2.ARM架构下CPU访问寄存器流程

在ARM架构下的CPU看来,对内存的访问与对外设寄存器的访问是一样的。

如上图所示:

ARM架构下的CPU向内存控制器发送地址信息,内存控制器会根据地址信息匹配到地址信息所对应的外设(匹配方式为地址信息是否介于某个外设在内存映射图中的地址范围),然后CPU再对内存控制器匹配到的外设进行读写操作对于RICS架构(ARM架构)的芯片,对于内存或外设只有读写操作,所有的计算都是在cpu内进行的)。

正是由于对于CPU来说,它不需要处理如何将地址信息匹配到相应的外设,因此,就有了内存图的概念。这些外设通过译码电路连接到地址总线上,每个外设都对应着相应的连续内存区间,就形成了内存图。举个例子,以I.MX6ULL为例:

如上图所示,每一个外设在内存图中都占有一段连续的存储空间,要对这些外设进行配置,就访问相应的地址空间。内存图大小为4G

1.3.ARM架构与X86架构外设区别

如上图所示:

在ARM架构中,是根据CPU发出不同的指令选择不同的设备。而在X86架构下,根据CPU发出的指令不同选择不同的设备。

1.4.RICS和CISC的比较

1.4.1.RICS

ARM芯片属于精简指令集计算机(RISC:Reduced Instruction Set Computing),它所用的指令比较简单,有如下特点:

① 对内存只有读、写指令

对于数据的运算是在CPU内部实现

③ 使用RISC指令的CPU复杂度小一点,易于设计

1.4.2.CISC

x86属于复杂指令集计算机(CISC:Complex Instruction Set Computing),

它所用的指令比较复杂,比如某些复杂的指令,它是通过“微程序”来实现的。

比如执行乘法指令时,实际上会去执行一个“微程序”,

在“微程序”里,

一样是去执行这4不操作:

① 读内存a

② 读内存b

③ 计算a*b

④ 把结果写入内存

但是对于程序员来说,

他看不到“微程序”,

他好像用一条指令就搞定了这一切!

1.4.3.RISC和CISC的比较

CISC的指令能力强,大多数指令使用率低却增加了CPU的复杂度,指令是可变长格式;

RISC的指令大部分为单周期指令指令长度固定操作寄存器,对于内存只有Load/Store操作

CISC支持多种寻址方式;RISC支持的单一寻址方式

CISC通过微程序控制技术实现;

RISC增加了通用寄存器,硬布线逻辑控制为主,采用流水线

CISC的研制周期长

RISC优化编译,有效支持高级语言

2.ARM架构下CPU内部寄存器

在ARM架构下,CPU对外设只有读取/写入的操作。那么,CPU内部是如何存储来自外设的数据的呢?

CPU内部有很多的寄存器无论是cortex-M3/M4,还是cortex-A7,CPU内部都有R0、R1、……、R15寄存器,它们可以用来“暂存”数据。

对于R13、R14、R15,还另有用途:

R13:别名SP(Stack Pointer),栈指针

R14:别名LR(Link Register),用来保存返回地址

R15:别名PC(Program Counter),程序计数器,表示下一个指令地址,写入新值即可跳转

如下图所示,Cortex-M3/M4和Cortex-A7的内部寄存器几乎差不多

在ARM架构下,CPU可以运行在多种模式下,正是由于CPU可以运行在多种模式下,所以才能够支持操作系统。

如上图所示,Cortex-A7中有九种运行模式,并且在有些模式下有自己独立的寄存器。

但是又出现了一个新的问题,比如,如果比较了两个数,结果保存在哪?

运算的结果保存在了XPSW中(程序状态字寄存器)通过这个寄存器的名字我们可以猜到,这个寄存器就是用来保存程序的状态。那这个寄存器里面到底能够保存哪些状态呢?

我们发现,不论是对于Cortex-M4还是对于Cortex-A7来说,PSR几乎没有什么区别。

3.ARM指令集

3.1.知识储备

  • 汇编语言的本质就是机器码,汇编语言是机器码的助记符,编译器编译的时候只是进行了替换而已
  • 指令集:就是一系列指令的集合。如今指令集有三种,ARM指令集Thumb指令集Thumb1指令集
  • 在程序前面用CODE32/CODE16/THUMB表示指令集:ARM/Thumb/Thumb2

3.2.指令集

一开始,ARM公司发布两类指令集:

① ARM指令集,这是32位的,每条指令占据32位,高效,但是太占空间

② Thumb指令集,这是16位的,每条指令占据16位,节省空间

要节省空间时用Thumb指令,要效率时用ARM指令。

一个CPU既可以运行Thumb指令,也能运行ARM指令。怎么区分当前指令是Thumb还是ARM指令呢?

程序状态寄存器中有一位,名为“T”,它等于1时表示当前运行的是Thumb指令。

那么问题又来了:

假设函数A是使用Thumb指令写的,函数B是使用ARM指令写的,在函数A中调用函数B如何实现呢?

我们可以往PC寄存器里写入函数B的地址,就可以调用B,

但是怎么让CPU在执行B函数是进入ARM状态,在返回执行A函数时进入Thumb状态?

调用函数A时,让PC寄存器的BIT0等于1,即:PC=函数A地址+(1<<0);

调用函数B时,让PC寄存器的BIT0等于0:,即:PC=函数B地址

但是发现这样太麻烦了,对于程序员来说,每写一个函数体,还要在函数体里面加上ARM或Thumb声明。因此引入了Thumb2指令集,它支持16位指令、32位指令混合编程。

有那么多指令集:ARM、Thumb、Thumb2,不好记啊!

不用区分它们,不用担心,

ARM公司推出了: Unified Assembly Language,简称UAL,统一汇编语言,你不需要去区分这些指令集。

注意:thumb2指令集只支持Cortex-M内核,Cortex-A内核的还是沿用原来的ARM和thumb指令集

3.3.汇编指令

在之后学习操作系统的时候,我们用经常用到的汇编指令也一下那么几条,没见过的直接GOOGLE就可以了。

MOV LDR/STR LDM/STM AND/OR ADD/SUB B/BL DCD ADR/LDR CMP

3.3.1.汇编指令分类

汇编指令可以分为几大类:数据处理、内存访问、跳转、饱和运算、其他指令

3.3.2.汇编指令的格式

UAL汇编格式为:

Operation表示各类汇编指令,比如ADD、MOV;

cond表示conditon,即该指令执行的条件;

S表示该指令执行后,会去修改程序状态寄存器;

Rd为目的寄存器,用来存储运算的结果;

Rn、Operand2是两个源操作数

3.3.3.立即数

 MOV  R0, #VAL

意图是把VAL这个值存入R0寄存器。

问:VAL可以是任意值吗?

答:不可以,必须是立即数。

问:为什么?

答:假设VAL可以是任意数,”MOV R0, #VAL”本身是16位或32位,哪来的空间保存任意数值的VAL?

所以,VAL必须符合某些规定。

3.3.4.伪指令

去判断一个VAL是否立即数,麻烦!并且我就是想把任意数值赋给R0,怎么办?

可以使用伪指令:

​ LDR R0, =VAL

“伪指令”,就是假的、不存在的指令。

注意:LDR作为“伪指令”时,指令中有一个“=”,否则它就是真实的LDR(load regisgter)指令了。

编译器会把“伪指令”替换成真实的指令,比如:

LDR R0, =0x12

0x12是立即数,那么替换为:MOV R0, #0x12

LDR R0, =0x12345678

0x12345678不是立即数,那么替换为:

LDR R0, [PC, #offset] // 2. 使用Load Register读内存指令读出值,offset是链接程序时确定的

……

Label DCD 0x12345678 // 1. 编译器在程序某个地方保存有这个值

3.3.5.内存访问指令

LDR:Load Register;LDM:Load Multiple Register;

STR:Store Register;STM:Store Multiple Register。

3.3.6.数据处理指令

3.3.7.跳转指令

核心指令是B、BL:

B:Branch,跳转

BL:Branch with Link,跳转前先把返回地址保持在LR寄存器中

3.3.8.ARM编译器和GCC编译器语法差异

在使用keil5对开发项目进行编译,使用的是ARM编译器,语法为armasm

在使用arm-linux-guneabihf-gcc对开发项目进行编译,使用的是GCC编译器,语法为GNU Assembler

虽然两者所使用到的关键字(语法)很大的不一样,但是对学习汇编没用太大的影响,语言不是难点。

4.ARM汇编模拟器

VisUAL是一款ARM汇编模拟器,

下载地址:https://salmanarif.bitbucket.io/visual/downloads.html

如果无法下载,可以联系我。VisUAL模拟的ARM板子如下图所示,它没有模拟外设,仅仅模拟了CPU、ROM、RAM。红色区域是ROM,不能读不能写,只能运行其中的程序;ROM区域本来可以读的,这是VisUAL的局限,RAM区域可读可写。

おすすめ

転載: blog.csdn.net/qq_46359697/article/details/113405646