指令集简述
"处理器只能执行由01组成的二进制序列".这句话相信已经在大家的脑海中回荡了数十年,那到底什么是处理器?所谓的二进制序列到底是什么?
这个问题想必很多朋友都有考虑过,但是始终不得解.甚至是对指令集,汇编也只是模模糊糊的知道有这个东西.在这一切都开始前首先明确一个简单的逻辑知识点:逻辑门电路是最基本的运算单元.逻辑门电路可以实现简单的算术运算,而驱动逻辑门电路的却是所谓的电,在抽象一点就是"正负电信号".而这个里的"正负电信号"就是所谓的二进制序列.
那么至此所谓的"二进制序列"就已经解释清楚了.但是二进制序列的组合方式无穷无尽,这就诞生了所谓的汇编.汇编可以理解为 按照 二进制序列的功能 对其进行命名,这样就可以在 英文单词 与 二进制序列 之间 搭起一个桥梁.
最基本的加法运算在逻辑门电路中有数不清的实现方式,以此类推同样的功能在不同的厂商手中有不同的实现方式.经过多年发展不同的厂商都发展出了各自特定的实现方式,这就是所谓的指令集.可以认为每个处理器都有自己独特的指令集,一般情况下新的处理器兼容旧处理器的指令集.
在嵌入式领域使用最多的就是 arm以及mips架构的处理器,本章接下去会对这两个汇编指令集做一些比较基本的介绍,方便大家在学习后面的章节时翻回来查阅
寄存器
名称 | 作用 | 备注 |
---|---|---|
R0(a1) | 通用寄存器 | 一般用于保存参数 |
R1(a2) | 通用寄存器 | 一般用于保存参数 |
R2(a3) | 通用寄存器 | 一般用于保存参数 |
R3(a4) | 通用寄存器 | 一般用于保存参数 |
R4(v1) | 通用寄存器 | 一般用于保存局部变量 |
R5(v2) | 通用寄存器 | 一般用于保存局部变量 |
R6(v3) | 通用寄存器 | 一般用于保存局部变量 |
R7(v4) | 通用寄存器 | 一般用于保存局部变量 |
R8(v5) | 通用寄存器 | 一般用于保存局部变量 |
R9(SB,V6) | 通用寄存器 | 一般情况下约定:静态基址寄存器(内存寻址的基地址) |
R10(SL,V7) | 通用寄存器 | 一般情况下约定:数据栈限制指针(限制栈大小) |
R11(FP,V8) | 通用寄存器 | 一般情况下约定:栈底 |
R12(IP) | 通用寄存器 | 一般情况下约定:内部程序调用暂存寄存器(变参,临时变量...) |
R13(SP) | 堆栈指针 | 栈顶 |
R14(LR) | 连接寄存器 | 保存返回地址 |
R15(PC) | 程序计数器 | 指向下一条要读取指令的地址 |
R16(CPSR) | 状态寄存器 | 表示当前处理器的状态 |
R17(SPSR) | 状态保存寄存器 | 异常处理中,备份 CPSR |
数据传输指令
名称 | 作用 | 备注 |
---|---|---|
mov r1, #0x1 | 数据传送 | r1 = 0x1 |
LDR | 读取数据 | 将指定地址上的字数据读入Rd |
STR | 数据保存 | 将Rd中的字数据存入指定地址 |
LDM | 批量加载内存中的寄存器 | |
STM | 批量保存寄存器到内存中 |
跳转指令
助记符 | 说明 | 操作 | 条件码位置 |
---|---|---|---|
B label | 分支指令 | PC←label | B{cond} |
BL label | 带链接的分支指令 | LR←(返回地址)-,PC←label | BL{cond} |
BX Rm | 带状态切换的分支指令 | PC←Rm,切换处理器状态 | BX{cond} |
BLX Rm/lable | 结合BX BL的功能 | 结合BX BL | BLX{cond} |
乘法指令
mips的运算指令和常规的x86区别不大,这里主要介绍以下乘法指令:
助记符 | 说明 | 操作 | 条件码位置 |
---|---|---|---|
MUL Rd,Rm,Rs | 32位乘法指令 | Rd←Rm*Rs (Rd≠Rm) | MUL{cond}{S} |
MLA Rd,Rm,Rs,Rn | 32位乘加指令 | Rd←Rm*Rs+Rn (Rd≠Rm) | MLA{cond}{S} |
UMULL RdLo,RdHi,Rm,Rs | 64位无符号乘法指令 | (RdLo,RdHi) ←Rm*Rs | UMULL{cond}{S} |
UMLAL RdLo,RdHi,Rm,Rs | 64位无符号乘加指令 | (RdLo,RdHi) ←Rm*Rs+(RdLo,RdHi) | UMLAL{cond}{S} |
SMULL RdLo,RdHi,Rm,Rs | 64位有符号乘法指令 | (RdLo,RdHi) ←Rm*Rs | SMULL{cond}{S} |
SMLAL RdLo,RdHi,Rm,Rs | 64位有符号乘加指令 | (RdLo,RdHi) ←Rm*Rs+(RdLo,RdHi) | SMLAL{cond}{S} |
比较指令
助记符 | 说明 | 操作 | 条件码位置 |
---|---|---|---|
CMP Rn, operand2 | 比较指令 | 标志N、Z、C、V←Rn-operand2 | CMP{cond} |
CMN Rn, operand2 | 负数比较指令 | 标志N、Z、C、V←Rn+operand2 | CMN{cond} |
TST Rn, operand2 | 位测试指令 | 标志N、Z、C、V←Rn & operand2 | TST{cond} |
TEQ Rn, operand2 | 相等测试指令 | 标志N、Z、C、V←Rn ^ operand2 | TEQ{cond} |
条件执行
arm所有的指令可以实现条件执行,只要在目标指令后面跟上对应的条件描述就行:
标志 | 含义 |
---|---|
EQ | 相等 |
NEQ | 不相等 |
CS/HS | 无符号数 大于等于 |
CC/LO | 无符号数 小于 |
MI | 负数 |
PL | 正数或0 |
VS | 溢出 |
VC | 没有溢出 |
HI | 无符号数大于 |
LS | 无符号数 小于等于 |
GE | 有符号数 大于等于 |
LT | 有符号数 小于 |
GT | 有符号数 大于 |
LE | 有符号数 小于等于 |
AL | 无条件执行 |
NV | 永远不执行 |
其他注意事项:
在arm中的数据存储单位和传统的x86有些许的不一样:
- 存储单位 字 表示 4个字节,数据存储指令 默认大小
- 存储单位 半个字 表示 2个字节,数据存储指令特征的特征字符为 H
- 存储单位 字节 表示 1个字节,数据存储指令特征的特征字符为 B
- 数据存储指令特征的特征字符为 S 表示有符号数据处理