一、汇编基本概要
1、ARM数据和指令类型
2、ARM字节顺序
即可大端存储也可小端存储,默认小端存储(不建议修改)、
kernel(内核)中的,CPSR(当前程序状态寄存器)可修改大小端存储
3、ARM处理器工作模式
前七个重要
4、寄存器组织
5、程序状态寄存器(CPSR)
此图可做概念理解,部分实际参数有问题
6、异常处理
(1)概念
异常向量表是ARM处理器中用于处理异常和中断的核心机制,包含各类异常处理程序的入口地址或跳转指令。当异常发生时,处理器会自动跳转到对应向量地址执行处理程序
(2)关键功能
快速响应异常,保存现场(LR、SPSR),切换处理器模式。
提供标准化异常入口,确保系统稳定性和实时性
(2)异常向量表
异常类型 | 向量地址 |
---|---|
复位(Reset) | 0x00000000 |
未定义指令(Undefined Instruction) | 0x00000004 |
软件中断(SWI) | 0x00000008 |
预取指令异常(Prefetch Abort) | 0x0000000C |
数据异常(Data Abort) | 0x00000010 |
保留(Reserved) | 0x00000014 |
外部中断(IRQ) | 0x00000018 |
快速外部中断(FIQ) | 0x0000001C |
二、实现汇编操作
1、格式
伪操作:它们不是 ARM 处理器实际的指令(如 MOV, ADD 等),而是写给汇编器看的命令,用于指导汇编器如何工作
area reset, code, readonly
code32
entry
end
area: 这是最重要的一个伪操作,用于定义一个段。程序、数据、堆栈等都需要被组织在不同的段中
reset: 这是你为这个段起的名字。名字 reset 具有很强的暗示性,通常用于表示复位向量段,即CPU上电或复位后首先执行的第一段代码所在的位置
code: 指定该段的属性为代码,意味着这个段包含可执行的指令
readonly: 指定该段的属性为只读。对于代码段来说,这通常是默认且必须的
code32: 表示后续指令使用 32位的 ARM 指令集
thumb: 表示后续指令使用 16位的 Thumb 指令集
2、指令
(1)mov
MOV{S}<c> <Rd>, #<const>
MOV{S}<c> <Rd>, <Rm>MOV instruction Canonical form
MOV{S} <Rd>, <Rm>, ASR #<n> ASR{S} <Rd>, <Rm>, #<n>
MOV{S} <Rd>, <Rm>, LSL #<n> LSL{S} <Rd>, <Rm>, #<n>
MOV{S} <Rd>, <Rm>, LSR #<n> LSR{S} <Rd>, <Rm>, #<n>
MOV{S} <Rd>, <Rm>, ROR #<n> ROR{S} <Rd>, <Rm>, #<n>
MOV{S} <Rd>, <Rm>, ASR <Rs> ASR{S} <Rd>, <Rm>, <Rs>
MOV{S} <Rd>, <Rm>, LSL <Rs> LSL{S} <Rd>, <Rm>, <Rs>
MOV{S} <Rd>, <Rm>, LSR <Rs> LSR{S} <Rd>, <Rm>, <Rs>
MOV{S} <Rd>, <Rm>, ROR <Rs> ROR{S} <Rd>, <Rm>, <Rs>
MOV{S} <Rd>, <Rm>, RRX RRX{S} <Rd>, <Rm>
- 注意
- (1)与C语言中的赋值运算对比(左值/右值),利于加深理解
- (2)#<n>/<Rs> 取值范围 (0 - 31)
- (3)RRX{S}:扩展右移 (不需要移位量)
- (4)在计算机中只识别二进制数据,计算机没有有无符号,浮动点等概念;
(2)add(加法指令)
立即数作为第二操作数: ADD{S}<c> <Rd>, <Rn>, #<const>
寄存器作为第二操作数寄存器: ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
寄存器作为第二操作数移位量: ADD{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
- 注意
- {, <shift>} 其中{}代表可选择,“,”表示在使用时需要在Rm后添加“,” shift 移位量(立即数)
- add r0, #3, #2 :为什么没有这种形式,C语言int a = 1 + 2; 编译阶段计算, 不需要在机器指令中体现
(3)sub(减法指令)
立即数作为第二操作数: SUB{S}<c> <Rd>, <Rn>, #<const>
寄存器作为第二操作数寄存器: SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
寄存器作为第二操作数移位量: SUB{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
(4)立即数(imm)
以上指令都有立即数作为第二操作数的情况,准确的说这里所指的是12位立即数imm12
12位立即数的条件是:
判断标准:把某个数展开成2进制,该数必须存在一种循环右移(偶数位),使得移位后高24位全0,低8位即为有效imm8;
(5)ldr(加载指令)
LDR<c> <Rt>, <label>
(6)sdr(存放指令)
(7)MVN(按位取反移动指令)
MVN{S}<c> <Rd>, #<const>
MVN{S}<c> <Rd>, <Rm>{, <shift>}
MVN{S}<c> <Rd>, <Rm>, <type> <Rs>
(8)bic(bit clear):指定位置清0
BIC{S}<c> <Rd>, <Rn>, #<const>
BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
BIC{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
(9)orr(or):指定位置1
ORR{S}<c> <Rd>, <Rn>, #<const>
ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ORR{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
(10)条件判断标志NZCV
CPSR寄存器中条件判断标志位
N: 符号标志位:上条指令执行结果最高位bit31为1,则 N = 1, 当结果作为有符号解释时为负值;
Z: 零值标志位:上条指令执行结果为0(即bit0 - bit31 均为0),则 Z = 1;
C: 进位标志位:进行无符号解读,如果在加法过程中进位或者减法时没有借位,则为 C = 1,否则 C = 0
V: 溢出标志位:进行有符号解读,是否发生溢出 -2^31 - 2^31-1(两个正数加得负数,两个负数加得正数)
条件码:eq ge gt le lt al(无条件执行)
equal:等于
not equal:不等于
(11)cmp(compare):比较指令
CMP<c> <Rn>, #<const>
CMP<c> <Rn>, <Rm>{, <shift>}
CMP<c> <Rn>, <Rm>, <type> <Rs>
cmp r0, r1 <==> subs r0, r1
比较两个数中的最大值
(12)b bl bx :(跳转指令)
类似于c语言goto
B<c> <label>
b fun <==> ldr pc, =fun
BL<c> <label>
bl fun
BX<c> <Rm>
bx lr <==> mov pc, lr