ARM汇编
6.ARM体系结构及指令
ARM体系结构
- 精简指令计算机结构(RISC)
- Load/store体系结构,只能处理寄存器的数据
- 固定指令长度、单周期指令
- 流水线
- 倾向于使用更多的寄存器用来存储数据
- ARM指令集跟RISC有一些差异
- 桶形位移寄存器:单周期内完成数据的各种位移操作
- 并不是所有ARM指令都是单周期
- Thumb指令集:32位ARM指令集的压缩形式,提高代码密度
- 条件执行:减少了分支数目,提高代码密度
- 增加DSP指令
ARM工作模式
处理器模式 | 模式编号 | 简介 |
---|---|---|
User mode | 0b10000 | 处理器正常运行时的工作模式 |
FIQ mode | 0b10001 | 快速中断模式,中断优先级比IRQ高 |
IRQ mode | 0b10010 | 中断模式 |
寄存器
- 通用寄存器
- R0~R12:其中R0到R3用来传递函数参数,R4到R11用来保存子程序的局部变量,R12常用作调用过程中的临时寄存器
- 程序计数器:R15(PC),不能用于其他用途,取指令地址指针,其值 = 当前内存指令执行地址+8
记死!!!!!!!!!!!
- 状态寄存器
- CPSR:当前处理器的状态(处理器模式) 一共5位
- 各模式下独立的寄存器
- 堆栈寄存器:R13(SP),在子程序中R13不能用作其它用途
- 链接寄存器:R14(LR),保存子程序的返回地址
- FIQ工作模式下,有自己的R8~R12寄存器
- SPSR:用于保存CPSR的工作状态,每个模式下都有一个寄存器
ARM寻址方式
将.c文件生成.s文件的方法
arm-linux-gnueabihf-gcc -S 1.c
-
寄存器寻址
- MOV R1, R2; 将R2的值搬入R1
- SUB R0, R1, R2; 结果保存到R0
- 操作数的值在寄存器中,指令中直接取值
-
立即寻址
- SUBS R0, R0, #1
- MOV R0, #0xFF00
- 立即数以#为前缀,0x表示16进制
-
寄存器偏移寻址
- MOV R0, R2, LSL, #3; R2左移3位---->R0
- 逻辑位移与算数位移
- 逻辑位移,空缺处补0
- 算术移位保证符号位不变,右移空缺处用符号位填,左移补0
- 常用的位移操作
- LSL:逻辑左移
- LSR:逻辑右移
- ASR/ASL:算术右移/左移
- ROR/ROL:循环右移/左移
- RRX:带扩展的循环右移
-
寄存器间接寻址
- 寄存器间接寻址
- 寄存器为操作数的地址指针
- C指针操作:寄存器间接寻址
- LDR R1, [R2]
- 将R2中的值作为内存地址,取出该内存地址中的数据送到R1
- SWP R1, R1, [R2]
- 将R2中的值作为内存地址,取出此地址中的数值与R1进行交换
- 寄存器间接寻址
-
基址寻址
- 基址寻址
- 寄存器中的值与给出的偏移量相加——地址
- 取出此地址中的值
- 常用于查表、数组操作、功能部件寄存器访问
- 分为前索引和后索引基址寻址
- STR R1, [R0, #-2]
- 先将R0中的值减2作为内存地址,再把R1的值写到此地址
- STR R1, [R0], #2
- 先将R0中的值作为内存地址,把R1中的值写到此地址,然后R0加2
- LDR R1, [R3, #0x03]
- 将R3中的数值加0x03作为内容地址,取出此地址中的值——R2
- 总结:STR就是将寄存器里的值放到地址,LDR就是将地址中的值放到寄存器
- 基址寻址
-
多寄存器寻址
- 一次可以传送几个寄存器值
- 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
-
堆栈寻址
——ARM中栈的操作- 子程序局部变量存储、参数传递要通过堆栈完成
- ARM指令集中没有出栈和入栈的专门指令
- ARM中栈的操作是通过STM/LDM和栈指针SP配合操作完成
- ARM采用栈的类型是满递减堆栈
——栈的分类
递增堆栈A:向上生长,向高地址方向增长
递减堆栈D:向下生长,向低地址方向增长
满堆栈 F:SP栈指针指向栈顶元素
空堆栈 E:SP栈指针指向下一次要入栈元素的地址 -
相对寻址
-
由PC作为基地址,指令中的地址码段作为偏移量
-
两者相加后得到的地址即为操作数的有效地址
-
常见指令:B、BL、adr
-
举例
...
B LOOP
...
-
LOOP MOV R0,#1
MOV R1,R0
...
此时B LOOP指令等价于ADD PC, PC, #OFFSET
其中OFFSET为B LOOP指令地址与LOOP标号地址之间的偏移
B的前后跳转范围:[0,32M]