汇编语言是与硬件接触的美妙语言,同时汇编语言又可以和C语言高度契合,在深入理解嵌入式时,汇编语言是一条不可忽略的一条道路。就像是记忆关键字一样记忆ARM的指令集,是一项必备的知识。
ARM处理器支持ARM指令集,也支持16位的Thumb指令集,从ARMv6开始,新的ARM处理器支持16/32位的Thumb-2指令集(ARMv7-M仅支持Thumb-2)。ARM指令集使用标准的,固定长度的32位指令格式,ARM处理器是RISC结构。
1.指令总结
ARM微处理器的指令集可以分为分支指令,数据处理指令,程序状态存储器指令,加载/存储指令,协处理器指令和异常产生指令共有六大类。
跳转指令
B 跳转指令 BL 带返回的跳转 BLX 带返回和状态切换的跳转指令 BX 带状态切换的跳转指令 CBZ 比较(Compare),如果结果为零(Zero)就转移(只能跳到后面的指令) CBNZ 比较,如果结果非零(Non Zero)就转移(只能跳到后面的指令)
数据处理指令
MOV 数据传送指令 数据传送类
SWP 交换指令 交换类
CMP 比较指令 比较类 CMN 比较反值指令
TEQ 相等测试指令 测试指令 TST 位测试指令
AND 逻辑与指令 逻辑运算类 BIC 位清零指令 EOR 异或指令 ORR 逻辑或指令
ADC 带进位加法指令 算术运算类 ADD 加法指令 MLA 乘加运算指令 MUL 32位乘法指令 MLA 32位乘加指令 RSB 逆向减法指令 RSC 带借位的逆向减法指令 SBC 带借位减法指令 SUB 减法指令
程序状态寄存器处理指令
MRS 传送CPSR或SPSR数据到通用寄存器指令 MSR 传送通用寄存器数据到CPSR或SPSR指令
加载/存储指令
LDC 存储器到协处理器的数据传送指令 LDM 加载多个寄存器指令 LDR 存储器到寄存器的数据传送指令 STM 批量内存字写入指令 STR 寄存器到存储器的数据传送指令
协处理器指令类
CDP 协处理器数据操作指令 MCR 从寄存器到协处理器的数据传送指令 MRC 从协处理器到寄存器的数据传送指令 STC 协处理器寄存器写入存储器指令
异常产生指令类
BKPT 断点中断指令 SWI 软件中断指令
2.指令条件域及条件码
当处理器工作在ARM状态时,指令根据CPSR中的条件码的状态和指令的条件域有条件的执行。当指令的执行条件满足,指令被执行,反之指令被忽略。每一条ARM指令包含4位的条件码,位于指令的最高4位【31::28】。条件码理论上有16种,实际上有15种可以使用。每种条件码用两个字符表示,可以添加在指令助记符后面与指令同时使用。
跳转指令B可以加上后缀EQ变为BEQ表示“相等则跳转”,既当CPSR中的Z标志置位时发生跳转。
条件码 | 助记符后缀 | 标志 | 含义 |
0000 | EQ | Z置位 | 相等 |
0001 | NE | Z清零 | 不相等 |
0010 | CS | C置位 | 无符号数大于或等于 |
0011 | CC | C清零 | 无符号数小于 |
0100 | MI | N置位 | 负数 |
0101 | PL | N清零 | 正数或零 |
0110 | VS | V置位 | 溢出 |
0111 | VC | V清零 | 未溢出 |
1000 | HI | C置位Z清零 | 无符号数大于 |
1001 | LS | C清零Z置位 | 无符号数小于或等于 |
1010 | GE | N等于V | 带符号数大于或等于 |
1011 | LT | N不等于V | 带符号数小于 |
1100 | GT | Z清零且(N等于V) | 带符号数大于 |
1101 | LE | Z置位或(N不等于V) | 带符号数小于或等于 |
1110 | AL | 忽略 | 无条件执行 |
3.移位操作符
LSL | 逻辑左移 | MOV R0,R1,LSL#2 |
ASL | 算术左移 | MOV R0,R2,ASL#2 |
LSR | 逻辑右移 | MOV R0,R1,LSR#2 |
ASR | 算术右移 | MOV R0,R2,ASR#2 |
ROR | 循环右移(内容循环右移) | MOV R0,R1,ROR#2 |
RRX | 扩展的循环右移(扩展到C标志) | MOV R0,R1,RRX#2 |
4.批量数据传送类型
IA | IB | DA | DB |
传送后地址加 | 传送前地址加 | 传送后地址减 | 传送前地址减 |
LDMIA R0,{R1,R2,R3-R7} |
5.异常中断指令
SWI | 软件中断指令 | SWI{cond} imm24 |
BKPT | 断点中断指令(保存断点信息) | BKRT imm16 |
6.ARM处理器支持的伪指令
ADR | 相对偏移地址加载到通用寄存器中 | ADR{cond} Rd,expr |
LDR | 用于一个32位常数的加载或地址的加载 | LDR{cond} Rd,=[expr|bael-expr] |
NOP | 空操作,延时 | NOP |
7.ARM编译器支持的伪指令
符号定义伪指令 | GBLA 全局变量名 | 定义一个全局数值变量,并初始化为0 |
GBLL 全局变量名 | 定义一个全局逻辑变量,并初始化为F | |
GBLS 全局变量名 | 定义一个全局字符变量,并初始化为空 | |
LCLA 局部变量名 | 定义一个局部数值变量,并初始化为0 | |
LCLL 局部变量名 | 定义一个局部逻辑变量,并初始化为F | |
LCLS 局部变量名 | 定义一个局部字符变量,并初始化为空 | |
变量名 SETA 表达式 | 给一个数值变量赋值 | |
变量名 SETL 表达式 | 给一个逻辑变量赋值 | |
变量名 SETS 表达式 | 给一个字符变量赋值 | |
名称 RLIST {寄存器列表} | 对一个通用寄存器列表定义名称 | |
数据定义伪指令 | 标号 DCB 表达式 | 分配一片连续的字节存储单元并对数据初始化 |
标号 DCW 表达式 | 分配一片连续的半字节存储单元并对数据初始化 | |
标号 DCD 表达式 | 分配一片连续的字存储单元并对数据初始化 | |
标号 DCQ 表达式 | 分配一片连续的双字节存储单元并对数据初始化 | |
汇编控制伪指令 | IF 逻辑表达式 指令序列1 ELSE 指令序列2 ENDIF |
|
WHILE 逻辑表达式 指令序列1 WEND |
||
其他伪指令 | AREA 段名,属性1,属性2,···· CODE 属性 DATA 属性 READONLY 属性 READWRITE 属性 ALLGN 属性 COMMON |
定义一个代码段或数据段 定义一个代码段,默认只读READONLY 定义一个数据段,可读写READWRITE 只读 读写 对齐方式,按照2^ALLGN直接对齐 通用段属性 |
CODE16 CODE32 |
指令一下指令为16位Thumb指令代码 指示以下指令为32位ARM指令代码 |
|
ENTRY | 汇编语言程序入口 | |
END | 汇编语言程序结束 | |
名称 EQU 表达式 [,类型] | 等于伪指令 | |
EXPORT 标号 | 全部标号声明伪指令 | |
IMPORT 标号 | 引入一个标号伪指令 | |
EXTERN 标号 | 外部标号引用声明伪指令 |
(保留补充RT-Thread的context_rvds.s文件片段解析)
ARM寄存器组织表<传送门>