ARM体系结构(ARM的7种工作模式和异常处理机制)与常用的ARM汇编指令集

CISC:
复杂指令集CPU,CISC体系的设计理念是用最少的指令来完成任务
(譬如计算乘法只需要一条MUL指令即可),因此CISC的CPU本身
设计复杂、工艺复杂,但好处是编译器好设计。
RISC:
精简指令集CPU,RISC的设计理念是让软件来完成具体的任务,
CPU本身仅提供基本功能指令集。因此RISC CPU的指令集中只有很少的指令,
这种设计相对于CISC,CPU的设计和工艺简单了,但是编译器的设计变难了。
IO与内存统一编址:
把外设的寄存器当作一个内存地址来读写,从而以访问内存相同的方式来操作外设。
IO与内存独立编址:
使用专用的CPU指令来访问某种特定外设。
冯诺依曼结构:
程序和数据都放在内存中,且不彼此分离的结构。
程序和数据不区分的放在一起,因此安全和稳定性是个问题,好处是处理起来简单。
哈佛结构:
程序(一般放在ROM、flash中)和数据(一般放在RAM中)独立分开存放,
因此好处是安全和稳定性高,缺点是软件处理复杂一些(需要统一规划链接地址等)。ARM是哈佛结构的。
ARM 有7个基本工作模式:
User : 非特权模式,大部分任务执行在这种模式
FIQ : 当一个高优先级(fast) 中断产生时将会进入这种模式
IRQ : 当一个低优先级(normal) 中断产生时将会进入这种模式
Supervisor :当复位或软中断指令执行时将会进入这种模式
Abort : 当存取异常时将会进入这种模式
Undef : 当执行未定义指令时会进入这种模式
System : 使用和User模式相同寄存器集的特权模式
注:除User(用户模式)是Normal(普通模式)外,其他6种都是Privilege(特权模式)。
Privilege中除Sys模式外,其余5种为异常模式。各种模式的切换,可以是程序员通过代码主动切换
(通过写CPSR寄存器);也可以是CPU在某些情况下自动切换。
常用寄存器图解:

ARM体系结构(ARM的7种工作模式和异常处理机制)与常用的ARM汇编指令集
ARM体系结构(ARM的7种工作模式和异常处理机制)与常用的ARM汇编指令集
关键寄存器CPSR寄存器图解(各个位代表的意思):
ARM体系结构(ARM的7种工作模式和异常处理机制)与常用的ARM汇编指令集
ARM异常处理机制:
ARM体系结构(ARM的7种工作模式和异常处理机制)与常用的ARM汇编指令集
注:图摘抄自朱老师物联网大讲堂课件,在这里对朱老师表示感谢
ARM汇编常用指令集:
ldr 指令将内存内容加载入通用寄存器。
str 指令将寄存器内容存入内存空间中。
ldr/str组合用来实现 ARM CPU和内存数据交换
数据处理指令:
数据传输指令 mov mvn
算术指令 add sub rsb adc sbc rsc
逻辑指令 and orr eor bic
比较指令 cmp cmn tst teq
乘法指令 mvl mla umull umlal smull smlal
前导零计数 clz
算术运算符:
ARM体系结构(ARM的7种工作模式和异常处理机制)与常用的ARM汇编指令集
cpsr访问指令:
mrs用来读psr,msr用来写psr
举例:
mcr p15, <opcode_1>, , , , {<opcode_2>}
opcode_1:对于cp15永远为0
Rd:ARM的普通寄存器
Crn:cp15的寄存器,合法值是c0~c15
Crm:cp15的寄存器,一般均设为c0
opcode_2:一般省略或为0
uboot中的例子:mcr p15, 0, r0, c1, c0, 0
跳转指令:
b 直接跳转(就没打开算返回)
bl 跳转前把返回地址放入lr中,以便返回,以便用于函数调用
bx 跳转同时切换到ARM模式,一般用于异常处理的跳转。
多寄存器访问指令:
ldr/str每周期只能访问4字节内存,如果需要批量读取、写入内存时太慢,解决方案是stm/ldm。
8种后缀:
ia(increase after)先传输,再地址+4
ib(increase before)先地址+4,再传输
da(decrease after)先传输,再地址-4
db(decrease before)先地址-4,再传输
fd(full decrease)满递减堆栈
ed(empty decrease)空递减堆栈
fa(·······) 满递增堆栈
ea(·······)空递增堆栈
举例:
stmia sp, {r0 - r12}
将r0存入sp指向的内存处(假设为0x30001000);然后地址+4(即指向0x30001004),将r1存入该地址;
然后地址再+4(指向0x30001008),将r2存入该地址······直到r12内容放入(0x3001030),指令完成。
一个访存周期同时完成13个寄存器的读写。
!的作用
ldmia r0, {r2 - r3}
ldmia r0!, {r2 - r3}
感叹号的作用就是r0的值在ldm过程中发生的增加或者减少最后写回到r0去,也就是说ldm时会改变r0的值。
^的作用
ldmfd sp!, {r0 - r6, pc}
ldmfd sp!, {r0 - r6, pc}^
^的作用:在目标寄存器中有pc时,会同时将spsr写入到cpsr,一般用于从异常模式返回。

汇编中的一些符号:
@ 用来做注释。可以在行首也可以在代码后面同一行直接跟,和C语言中//类似
# 做注释,一般放在行首,表示这一行都是注释而不是代码。
:以冒号结尾的是标号
. 点号在gnu汇编中表示当前指令的地址
# 立即数前面要加#或$,表示这是个立即数
常用伪指令:
ldr 大范围的地址加载指令
adr 小范围的地址加载指令
adrl 中等范围的地址加载指令
nop 空操作
.global _start @ 给_start外部链接属性
.section .text @ 指定当前段为代码段
.ascii .byte .short .long .word
.quad .float .string @ 定义数据
.align 4 @ 以16字节对齐
.balignl 16 0xabcdefgh @ 16字节对齐填充
.equ @ 类似于C中宏定义
.end @标识文件结束
.include @ 头文件包含
.arm / .code32 @声明以下为arm指令
.thumb / .code16 @声明以下为thubm指令