一、RISC 与 CISC
1. CISC(复杂指令集计算机)
CISC: 指令长度可变,单条指令可以完成复杂操作;硬件实现复杂,需要更多晶体管;指令执行时间差异大,更依赖硬件电路实现复杂功能。
2. RISC(精简指令集计算机)
RISC:采用精简且统一长度的指令集,每条指令功能简单,多数可在一个时钟周期内完成;依赖编译器将复杂操作分解为简单指令;通常配备更多通用寄存器,硬件结构相对简单。
特点:执行效率高、功耗低、适合移动设备和嵌入式场景。
ARM 属于RISC架构。
二、ARM 内核的组成部分
1、运算单元(ALU)
执行算术(如加减)和逻辑(如与或非)运算。
2、寄存器组
包括通用寄存器(如 R0 - R15)、程序计数器(PC,指向当前执行指令地址)、链接寄存器(LR,用于函数调用返回地址保存)、栈指针(SP,指向栈顶)等,用于临时存储数据与指令执行上下文。
3、控制单元
负责指令的解码、调度与执行控制,协调内核各部分工作。
4、存储管理单元(MMU)
实现虚拟内存与物理内存的映射,提供内存保护等功能,提升系统内存管理的灵活性与安全性。
5、高速缓存(CACHE)
分为指令缓存(I - cache)和数据缓存(D - cache),用于缓存常用指令和数据,减少 CPU 与主存之间的访问延迟,提高运行速度。
三、RAM 与 ROM 的分类
1、RAM 的分类
2、ROM 的分类
四、ARM9 与 Cortex - A 的工作模式
1. ARM9 的工作模式
1)用户模式(User)
非特权模式,大部分应用程序运行在此模式,权限最低,不能直接访问系统级资源。
2)快速中断模式(FIQ)
当高优先级(fast)中断产生时进入,用于快速处理对时间敏感的中断请求,可快速响应并处理紧急事件。
3)外部中断模式(IRQ)
当普通优先级(normal)中断产生时进入,处理一般的外部中断,如外设中断等。
4)管理模式(Supervisor)
操作系统使用的保护模式,在系统启动或执行系统调用时进入,具备较高权限,可管理系统资源。
5)数据访问终止模式(Data Abort)
数据访问异常时进入,用于处理数据访问相关的错误,如非法内存访问。
6)未定义指令模式(Undefined)
执行未定义指令时进入,可用于软件模拟未实现的指令等场景。
7)系统模式(System)
使用与 User 模式相同寄存器集的特权模式,为了兼容而扩展,权限高,可执行系统级操作。
2. Cortex - A 的工作模式
Cortex - A 系列包含ARM9的工作模式的同时,引入了 Monitor 模式 ,是为了安全而扩展出的、用于执行安全监控代码的模式。
五、ARM9 与 Cortex - A 的寄存器数量
1、ARM9
ARM9有 37 个寄存器(包含 31 个通用寄存器,以及 PC、LR、SP 等特殊功能寄存器)。
2、Cortex - A
Cortex - A 有 40 个寄存器(在 ARM9 基础上,根据架构演进和功能扩展,增加了部分寄存器以支持更复杂的操作与特性)。
六、异常处理与异常向量表
异常向量表:是 ARM 系统中一段预先定义好的内存区域,用来存放函数跳转地址的集合,其中每个异常(如复位、未定义指令、中断等)都对应一个固定的内存地址(即异常向量地址)。当异常产生时,ARM 内核会自动跳转到异常向量表中对应异常的地址处,执行该地址指向的异常处理程序入口代码,从而启动对该异常的处理流程。
七、立即数
1、什么是立即数
立即数(Immediate Value)指的是直接嵌入在机器指令中,无需从内存或寄存器读取的常数。它是指令的一部分,能快速参与运算(像加减、比较、赋值等操作),避免了额外的内存访问,从而提升指令执行效率。
2、12 位立即数的判断
1)如果某个数的数值范围在 0~0xFF 之间,那么这个数一定是立即数;
2)把某个数展开成二进制,这个数的最高位1至最低位1之间的二进制数序列的位数不能超过8位;
3)这个数的二进制序列凑够 8 位之后的右边必须为偶数个连续的0。
八、汇编指令 s 后缀的含义
1、定义
汇编指令 s 后缀:指在执行指令过程中会更新CPSR寄存器的N、V、C、Z位,几乎所有的汇编指令都可以在指令后面加上 s 后缀。
1)N 位
在结果是有符号的二进制补码情况下,如果结果为负数,则N=1;如果结果为非负数,则N=0
2)Z 位
如果结果为0,则Z=1;如果结果为非零,否则Z=0
3)C 位
是针对无符号数最高有效位向更高位进位时C=1;减法中运算结果的最高有效位从更高位借位时C=0
4)V 位
该位是针对有符号数的操作,会在下面两种情形变为1,两个最高有效位均为0的数相加,得到的结果最高有效位为1;两个最高有效位均为1的数相加,得到的结果最高有效位为0;除了这两种情况以外V位为0
2、用途
3、应用示例
三个数比较大小
area reset, readonly, code
code32
entry
mov r0, #3
mov r1, #6
mov r2, #2
cmp r0, r1
movls r3, r1 ;<=
movge r3, r0 ;>=
cmp r3, r2
movls r3, r2
end
九、b、bl、bx 指令的区别
指令 | 核心功能 | 是否保存返回地址(到 lr) | 是否切换指令集 | 典型用途 |
---|---|---|---|---|
b |
单纯跳转 | 否 | 否 | 循环、条件分支 |
bl |
跳转 + 保存返回地址 | 是 | 否 | 函数调用(同指令集内) |
bx |
跳转 + 切换指令集 | 否 | 是(根据目标地址 bit0) | ARM 与 Thumb 模式互跳 |
十、四种栈类型的区别
栈类型 | SP 指向位置 | 增长方向 | 入栈操作(Push) | 出栈操作(Pop) | 典型架构示例 |
---|---|---|---|---|---|
满减栈(FD) | 最后一个有效元素 | 向低地址增长 | SP 先减 n,再存数据 | 先读 SP 位置数据,再 SP 加 n | ARM 默认 |
满增栈(FA) | 最后一个有效元素 | 向高地址增长 | SP 先加 n,再存数据 | 先读 SP 位置数据,再 SP 减 n | 部分嵌入式系统 |
空减栈(ED) | 下一个空闲位置 | 向低地址增长 | 先存数据到 SP 位置,再 SP 减 n | SP 先加 n,再读新 SP 位置数据 | 较少见 |
空增栈(EA) | 下一个空闲位置 | 向高地址增长 | 先存数据到 SP 位置,再 SP 加 n | SP 先减 n,再读新 SP 位置数据 | x86 默认 |
(其中 n 为数据宽度,如 32 位 CPU 中 n=4)
ARM 内核默认使用的是满减栈(Full Descending,FD)。
十一、ARM 汇编与 C 函数相互调用的规则
1、 ARM汇编函数调用C函数
1)使用 stmfd 保护现场,使用 ldmfd 恢复现场;
2)在汇编代码中使用 import 对调用 C函数 进行声明;
3)传参时使用通用寄存器 r0~r3,进行传参,参数个数超过四个时,使用栈来传参;
4)C函数 的返回值使用 r0 来返回。
2、C函数调用ARM汇编函数
1)在汇编代码中使用 export 导出调用 汇编函数;
2)在 C函数 中使用 extern 声明 ARM汇编函数;
3)传参时使用通用寄存器 r0~r3,进行传参,参数个数超过四个时,使用栈来传参;
4)C函数 的返回值使用 r0 来返回。
十二、部分指令说明
1、LDR
LDR{<c>}{<q>} <Rt>, <label> ;如ldr r0, =0x2FAB4 |
功能:寄存器加载指令 如: LDR R0,[R1,#4] ;将内存地址为R1+4的字数据读入寄存器R0 ldr r0, [r1], #8 ;将内存地址R1的字数据读入r0,之后r1+8 LDR R0,[R1,#8] ! ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。 |
2、BIC
BIC{S}<c> <Rd>, <Rn>, #<const> |
功能:指定位清零指令 将 Rn 中的字数据const为1的比特 清0,把结果放入Rd |
3、ORR
ORR{S}<c> <Rd>, <Rn>, #<const> |
功能:指定位置位指令 将 Rn 中的字数据const为1的比特 置1,把结果放入Rd |
4、CMP
CMP比较指令用于比较两个寄存器的值或者比较一个寄存器和立即数的值,其原理是对待比较的两个数求差,看结果是否为0,这个指令会无条件修改N、V、C、Z位。
5、B
跳转指令b:b指令类似c语言的goto语句,能够实现无条件跳转。跳转时需要一个lable,表示要跳转到什么地方去。
6、STMDB(STMFD)
STMFD<c> <Rn>{!}, <registers> |
功能:入栈保护指令 Rn:栈底指针寄存器 < registers >:需要入栈保护的寄存器 ! :入栈之后sp自动自减 如:stmfd sp!, {r0, r1, r2, r3-r12, lr} |
7、LDMFD
LDMFD<c> <Rn>{!}, <registers> |
功能:出栈恢复指令 Rn:栈底指针寄存器 < registers >:需要入栈保护的寄存器 ! :出栈之后sp自动自增。 如:ldmfd sp!, {r0, r1, r2, r3-r12, lr} |
8、MRS 与 MSR
1)MRS
MRS<C> <Rd>, <spec_reg> |
功能:读取某个特殊寄存器 |
2)MSR
MSR<c> <spec_reg>, <Rd> |
功能:将 Rd 的内容写入某个特殊寄存器 |
转为 User 工作模式的代码
mrs r0, cpsr
bic r0, r0, #0x1F //置0
orr r0, r0, #0x10 //置1
msr cpsr_c, r0
十二、应用示例
1、STR 加载指令
ldr r0, =0x40000000
ldr r1, = 0x3456781A
ldr r2, [r1] ;r2 = *r1
str r1, [r0] ;*r0 = r1
str r1, [r0, #4] ;*(r0 + 1) = r1
str r1, [r0], #4 ;*r0++ = r1
str r1, [r0, #4]! ;*++r0 = r1
2、使用跳转指令实现三个数中最大值的寻找
mov r0, #3
mov r1, #6
mov r2, #2
cmp r0, r1
bls less
bgt great
less
mov r3, r1
b lable
great
mov r3, r0
lable
cmp r3, r2
bls less1
bgt finished
less1
mov r3, r2
finished
b finished
3、实现1~100的求和
mov r0, #1 ;i
mov r1, #0 ;sum
loop
cmp r0, #100
bgt finished
add r1, r1, r0
add r0, r0, #1
b loop
finished
b finished
4、ARM汇编函数 调用 C函数
area reset, readonly, code
preserve8
code32
entry
ldr pc, =_start
_start
ldr sp, =0x40001000
stmfd sp!, {r0 - r12, lr}
import c_max
mov r0, #2
mov r1, #5
bl c_max
ldmfd sp!, {r0 - r12, lr}
mov r0, #11
mov r1, #22
finished
b finished
end
int c_max(int a, int b)
{
return a > b ? a : b;
}
【END】