ARM体系结构及指令
1 ARM体系结构
1.1 精简指令计算机结构(RISC)
• Load/store体系结构,只能处理寄存器的数据 (从内存里加载)
• 固定指令长度、单周期指令
• 流水线
• 倾向于使用更多的寄存器用来存储数据
1.2 ARM指令集跟RISC有一些差异
• 桶形移位寄存器:单周期内完成数据的各种移位操作
• 并不是所有ARM指令都是单周期
• Thumb指令集:32位ARM指令集的压缩形式,提高代码密度
• 条件执行:减少了分支指令数目,提高代码密度
• 增加DSP指令
1.3 ARM工作模式
1.4 寄存器
各个模式下的寄存器定义
CPSR寄存器
2 ARM寻址方式
2.1 寄存器寻址
操作数的值在寄存器中,指令中直接取值
MOV R1,R2 //将R2的值搬入R1
SUB R0,R1,R2 //R1-R2,结果保存到R0
2.2 立即寻址
指令中直接给出立即数
SUBS R0,R0,#1 //r0 -1
MOV R0,#0xFF00 // 给r0赋值
2.3 寄存器偏移寻址
类似于寄存器寻址,不过增加了偏移操作
MOV R0,R2,LSL,#3 //R2左移3位R0
- 逻辑移位与算术移位
• 逻辑移位,空缺处补0
• 算术移位保证符号位不变,右移空缺处用符号位填,左移补0 - 常用的移位操作
• LSL:逻辑左移
• LSR:逻辑右移
• ASR/ASL:算术右移/左移
• ROR/ROL:循环右移/左移
• RRX:带扩展的循环右移
2.4 寄存器间接寻址
寄存器为操作数的地址指针,如C指针操作。
LDR R1,[R2]
//将R2中的值作为内存地址,取出该内存地址中的数据送到R1
SWP R1,R1,[R2]
//将R2中的值作为内存地址,取出此地址中的数值与R1进行交换
2.5 基址寻址
相当于 寄存器+偏移量后间接寻址。
常用于查表、数组操作、功能部件寄存器访问
分为前索引和后索引基址寻址
STR R1,[R0,#-2]
//先将R0中的值减2作为内存地址,再把R1的值写到此地址
STR R1,[R0],#2
//先将R0中的值作为内存地址,把R1中的值写到此地址,然后R0加2
LDR R2,[R3,#0x03]
//将R3中的数值加0x03作为内存地址,取出此地址中的值R2
2.6 多寄存器寻址
一次可以传送几个寄存器值
LDMIA R1!,{R2-R7,R12}
//将R1地址单元中的数据读出到R2-R7,R12,R1自动加1
STMIA R0!,{R3-R6,R10}
//将R3-R6,R10中的数据保存到R0指向地址,R0自动加1
- 寄存器列表中顺序不重要,最终编号小的寄存去会与内存低地
址相对应 - 连续的寄存器可用-连接,寄存器之间用,隔开
- LDM/STM可以接IA、IB、DA、DB,分别表示increase after、
increase before、decrease after、decrease before
2.7 堆栈寻址
ARM中栈的操作
- 子程序局部变量存储、参数传递要通过堆栈完成
- ARM指令集中没有出栈和入栈的专门指令
- ARM中栈的操作是通过STM/LDM和栈指针SP配合操作完成
- ARM采用栈的类型是满递减堆栈
栈的分类
- 递增堆栈 A:向上生长,向高地址方向增长
- 递减堆栈 D:向下生长,向低地址方向增长
- 满堆栈 F:SP栈指针指向栈顶元素
- 空堆栈 E:SP栈指针指向下一次要入栈元素的地址
STMFD和LDMFD可配对使用,完成堆栈的入栈和出栈操作,方便
STMFD SP!,{R1-R7,LR} //将R1-R7,LR入栈。满递减堆栈
LDMFD SP!,{R1-R7,LR} //数据出栈,弹出到R1-R7,LR,满递减堆栈
2.8 相对寻址
由PC作为基地址,指令中的地址码段作为偏移量
- 两者相加后得到的地址即为操作数的有效地址
- 常见指令:B、BL、ADR
B的前后跳转范围:[0,32M]
B LOOP // 此时B LOOP指令等价于ADD PC, PC, #OFFSET
// 其中OFFSET为B LOOP指令地址与LOOP标号地址之间的偏移
LOOP MOV R0,#1
MOV R1,R0
缺点:每次跳转都要计算偏移,然后操作PC指针 速度稍慢