嵌入式-ARM学习(一)
ARM有哪些工作模式?
ARM共有七种工作模式
- 用户模式(User)
非特权模式,也就是正常程序执行的模式,大部分任务在这种模式下执行。在用户模式下,如果没异常发生,不允许应用程序自行改变处理器的工作模式,如果又异常发生,处理器会自动切换工作模式。 - FIQ模式 (FIQ)
快速中断模式,支持高速数据传输和通道处理,当一个高优先级(fast)中断产生时将会进入这种模式。 - IRQ模式 (IRQ)
普通中断模式,当一个低优先级(normal)中断产生时将会进入这种模式。在这种模式下按中断的处理器方式又分为向量中断和非向量中断两种。通常的中断都在IRQ模式下进行。 - SVC模式(SVC)
管理模式,它是一种操作系统保护模式。当复位或软中断指令执行时处理器将进入这种模式。 - 中止模式(Abort)
当存取异常时将会进入中止模式,用来处理存储器故障,实现虚拟存储或存储保护。 - 未定义指令异常模式(undefined)
当执行未定义指令时会进入这种模式,主要是用来处理未定义的指令陷阱,支持硬件协处理器的软件仿真,因为未定义指令多发生在对协处理器的操作上。 - 系统模式(System)
使用和User模式相同寄存器组的特权模式,用来运行特权级的操作系统任务。
ARM核有多少个寄存器?
ARM处理器共有37个寄存器,这些寄存器包括以下两类寄存器
31个通用寄存器:包括程序计数器PC等,这些寄存器都是32位寄存器。
6个状态寄存器:状态寄存器也是32位的寄存器,但是目前只使用了其中的14位。

- R12:中间结果保存寄存器
- R13(SP):栈指针
- R14(LR):连接寄存器
- R15(PC):程序计数寄存器
程序状态寄存器有几个域?
32位的程序状态寄存器分为四个域:控制域,扩展域,状态域和标志域。


- C 控制域屏蔽字节(PSR[7:0])
- X 扩展域屏蔽字节(PSR[15:8])
- S 状态域屏蔽字节(PSR[23:16])
- F 标志域屏蔽字节(PSR[31:24])
mode位 — 处理器模式位
| Mode位 | 模式 |
|---|---|
| 10000 | User mode |
| 10001 | FIQ mode |
| 10010 | IRQ mode |
| 10011 | SVC mode |
| 10111 | Abort mode |
| 11011 | Undined mode |
| 11111 | System mode |
ARM指令编码格式

ARM指令

补充:
加载/存储指令: LDR,STR
条件判断汇总

GNU ARM 汇编伪指令(Assembler Directives)
此部分详文可参考博文GNU ARM 汇编伪指令(Assembler Directives)
以下列举一些常见伪指令
.text @将定义符开始的代码编译到代码段
.data @将定义符开始的代码编译到数据段
.end @文件结束
.equ GPG3CON, 0XE03001C0 @定义宏(即用GPG3CON代替0XE03001C0)
.byte @定义变量1字节
.byte 0x11,'a',0 @定义字节数组
.word @定义word变量(4字节 32位机)
.word 0x 12344578, 0x33445566
.space @预留给定字节空间,并设置为0或fill_byte
.space 128*2 @等同于malloc(128*2);
.string @定义字符串
.string "abcd\0"
.global _start @声明_start 为全局符号
ldr r0, =0xE0028008 @载入大常数0xE0028008到r0中
ldr r0, =buf @伪指令 把buf的值赋给r0
ARM寻址
此部分详文可参考博文ARM的9种寻址方式
以下列举一些常见寻址方式
立即寻址
操作数是立即数,以“#”为前缀,表示 16 进制数值时以“0x”表示。
例:
MOV R0,#0xFF00 //0xFF00 -> R0
SUBS R0,R0,#1 //R0 – 1 -> R0
寄存器寻址
操作数的值在寄存器中,指令执行时直接取出寄存器值操作。
例:
MOV R1,R2 //R2 -> R1
SUB R0,R1,R2 //R1 - R2 -> R0
寄存器偏移寻址
当第二操作数是寄存器偏移方式时,第二个寄存器操作数在与第一个操作数结合之前,选择进行移位操作。
例:
MOV R0,R2,LSL #3 //R2 的值左移 3 位,结果放入 R0,即 R0 = R2 * 8
ANDS R1,R1,R2,LSL #3 //R2 的值左移 3 位,然后和 R1 相与操作,结果放入 R1
可采用的移位操作:
LSL:逻辑左移(Logical Shift Left),低端空出位补 0
LSR:逻辑右移(Logical Shift Right),高端空出位补 0
ASR:算术右移(Arithmetic Shift Right),移位过程中符号位不变,即源操作数为正数,则高端空出位补 0,否则补 1
ROR:循环右移(Rotate Right),由低端移出位填入高端空出位
RRX:带扩展的循环右移(Rotate Right eXtended by 1 place),操作数右移一位,高端空出位用原 C 标志值填充。
寄存器间接寻址
操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。
例:
LDR R1,[R2] //将 R2 中的数值作为地址,取出此地址中的数据保存在 R1 中
SWP R1,R1,[R2] //将R2中的数值作为地址,取出此地址中的数值与 R1 中的值**
基址寻址
将基址寄存器的值与偏移量相加,形成操作数的有效地址,基址寻址用于访问基址附近的存储单元,常用于查表、数组操作、功能寄存器访问等。
例:
LDR R2,[R3,#0x0F] //将R3中的数值加 0x0F 作为地址,取此地址的值保存在 R2 中
STR R1,[R0,#-2] //将R0中的数值减 2 作为地址,把 R1的值保存到此地址中
多寄存器寻址
一次传送多个寄存器值,允许一条指令传送 16 个寄存器的任何子集或所有寄存器。多寄存器寻址时,寄存器子集按由小到大的顺序排列,连续的寄存器可用“-”连接,否则,用“,”分隔书写。
例:
LDMIA R1!,{R2-R7,R12} //将 R1的值读出到 R2-R7,R12,过程中R1 自动加 1
STMIA R0!,{R3-R6,R10} //将 R3-R6,R10的值保存到 R0 指向的地址,过程中R0 自动加 1
堆栈寻址
堆栈寻址使用堆栈指针SP,即R13,指向堆栈的栈顶。堆栈可分为两种:
向上生长:向高地址方向生长,称为递增堆栈,
向下生长:向低地址方向生长,称为递减堆栈,
堆栈指针指向最后压入的有效数据项,称为满堆栈,
堆栈指针指向下一个要放入的空位置,称为空堆栈,这样就有 4 种类型的堆栈。
-
满递增:堆栈地址向上增长,堆栈指针指向有效数据的最高地址。如 LDMFA,STMFA。
-
空递增:堆栈地址向上增长,堆栈指针指向堆栈上的第一个空位置。如 LDMEA,STMEA 。
-
满递减:堆栈地址向下增长,堆栈指针指向有效数据项的最低地址。如 LDMFD,STMFD。
-
空递减:堆栈地址向下增长,堆栈指针指向堆栈下的第一个空位置。如 LDMED,STMED 。
例:
STMFD SP!,{R1-R7,LR} //将 R1~R7,LR 入栈。满递减堆栈。
LDMFD SP!,{R1-R7,LR} //数据出栈,放入 R1~R7,LR 寄存器。满递减堆栈。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)