ARM体系结构与汇编

ARM(Adavanced RISC Machine)

RISC 精简指令集多数指令单周期完成,大多数ARM核都实现两种指令集,32-bit ARM 指令集16-bit Thumb 指令集

ARM的三级流水线

PC寄存器:保存的是当前正在执行的指令的地址

ARM三级流水线包括:

  • 取指(fetch)

  • 解码(decode)

  • 执行(execute)

在ARM指令集下执行三步操作,要从当前正在执行指令的地址进行偏移,每次偏移4个字节,而Thumb指令集每次偏移2个字节。

偏移量要对齐,防止出现对内存的非对齐访问!!!

指令周期数(CPI)= 单位周期内执行的指令条数

6个指令周期,4条指令 CPI = 6/4 = 1.5

并不是流水线越长,cpu的执行效率就越高,要根据指令的平均执行周期数决定。

ARM9及以后的版本使用的都是哈佛体系结构,ARM9中的流水线为5级。

ARM编程模型

ARM的工作模式

ARM有七种工作模式,可以分为特权模式非特权模式,也可以分为异常模式非异常模式

image-20230201113125311

前5种为异常模式,后2种为正常模式

前6种为特权模式,最后1种为非特权模式

ARM的工作状态

通常ARM处理器工作状态有两种:ARM工作状态(word 32bit)和Thumb工作状态(half-word 16bit),ARM工作状态执行的是ARM指令,Thumb工作状态执行的是Thumb指令。

切换方法

使用指令进行切换

BX Rm指令

Rm[0] = 0 进ARM状态

Rm[0] = 1 进THUMB状态

处理器自动切换

​ 处理器进行异常处理 (IRQFIQUndefSWIAbort)若在Thumb状态,则进入ARM状态,异常处理返回后进入Thumb状态。

只有在ARM工作状态下才能处理异常,如果是在Thumb状态下,要切换到ARM状态下处理异常,处理完后还要切换回ARM状态。

ARM的寄存器结构

这里的寄存器和STM32中的寄存器不同,这里的寄存器指的是CPU内部的寄存器。我们把STM32中能用物理地址直接访问到的外设的寄存器称为特殊功能寄存器,而现在的寄存器就是寄存器。

ARM有37个 32bit寄存器(ARM和mips中寄存器都是32bit),由31个通用寄存器 + 6个状态寄存器组成。其中6个状态寄存器,1个CPSR(当前值状态寄存器),5个SPSR(保存状态的寄存器),SPSR可以看作CPSR的备份寄存器,其中5个SPSR和上面5种异常模式是对应的。

ARM 有 37 个32位寄存器,每种模式下访问这些寄存器的一个子集

image-20230201194411513

ARM寄存器的组织结构

上面37个寄存器并不是同时都使用的,而是处于某一个模式的时候选取使用。

image-20230201111559110

寄存器和特殊功能寄存器的区别:

  1. 存在的位置不同

    • 寄存器存在ARM core内部,特殊功能寄存器在外部
  2. 访问的方式不同

    • 特殊功能寄存器有特定的物理地址,寄存器只有名字没有地址,很难用C访问到

在ARM中有37个32bit的寄存器(register),其中31个是通用寄存器,它们的命名方式是r0~r15,其中特殊的需要记住的有:

  • r11(fp frame pointer)帧指针
  • r13(sp stack pointer)栈指针
  • r14(lr保存函数的指针)
1
2
3
4
5
6
7
8
9
10
func()
{
...
return ;
}
main()
{
func();//i++指令的地址保存到lr寄存器中
i++;
}
  • r15(pc 保存的是取指令的地址)
  • 6个状态寄存器
    • 1个程序状态寄存器 cpsr
    • 5个状态寄存器 spsr

程序状态寄存器cpsr/spsr

cpsr是32bit的,其中高4位是NZCV位,每一位都有特殊的含义,称为条件标志位

  • [28] V 有符号的数据在做运算的时候有进位 V = 1
  • [29] C 运算结果有进位 C = 1
  • [30] Z 运算结果为0 Z = 1
  • [31] N 运算结果为负数 N = 1

[0:4]:模式位(Mode),标识当前ARM核工作在哪种模式下。

一共有7种模式,这7中模式公用一个cpsr,当切换模式的时候,每种模式的cpsr就需要改变。

M[4:0] 处理器模式
0b10000 用户模式
0b10001 FIQ模式
0b10010 IRQ模式
0b10011 管理模式
0b10111 终止模式
0b11011 定义模式
0b11111 系统模式

[5]:T位,标识的是当前ARM核的工作状态,Thumb = 1,ARM = 0

[6]:FIQ(快速中断)禁止,写1禁止

[7]:IRQ(普通中断)禁止,写1禁止

异常和异常向量表

ARM core支持5种异常:

  1. 按下reset键,执行swi指令进入SVC异常
  2. 执行到不认识的指令会进入undef异常
  3. 取指令的时候,非法访问存储器会进入abort异常
  4. 按下按键,按键中断进入irq异常
  5. 高优先级的中断进入fiq异常

当异常产生之后,ARM core硬件上会自动做4件事:

  1. 备份CPSR 到 SPSR_<mode>
  2. 设置 CPSR 对应的位
  3. 保存异常函数的返回地址 lr_<mode>(保护现场)
  4. pc跳转到异常向量的入口地址

image-20230201205423969

从异常返回,软件上要干两件事:

  1. cpsr = spsr_<mode> (恢复现场)
  2. pc = lr_<mode>

ARM支持的数据类型

数据类型 字节
double-word 8bit
word 4bit
half-word 2bit
Byte 1bit

需要汇编的情况

  • 系统优化
  • 中断处理,服务程序
  • Debug的时候,分析C语言难以分析
  • 初始化硬件平台

为什么开发板不能直接执行C语言代码,一定要初始化硬件平台?

内存还没有初始化,没有C执行的环境

对齐方式

32bit情况下都要采用4字节对齐,4字节对齐就是存储器的地址能被4整除。

大小端判断

验证arm处理器采用的段模式

1
2
3
4
5
6
7
8
9
10
int a = 0x12345678;

字节序:
大端模式 小端模式
0x100 12 78
0x101 34 56
0x102 56 34
0x103 78 12

低地址里存低位是小端(低低小),低地址里存高位是大端(低高大)

编程实现大小端的判断

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main()
{
unsigned int num = 0x12345678;
unsigned char *p = (unsigned char *) &num;
if (*p == 0x12)
printf("Big Endian\n");
else
printf("Little Endian\n");
return 0;
}