ARM汇编
ARM 汇编
汇编语言特点
- 汇编的实质:机器指令(机器码)的助记符,是一种低级符号语言,是一款CPU的本质特征
- 不同CPU的机器指令集设计不同,汇编语言不能在不同CPU之间互相移植
- 汇编程序可以充分发挥CPU的设计特点,在操作系统内核中效率极其重要处都需要用汇编处理
ARM汇编指令
ARM汇编指令与伪指令
- 指令
CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以由CPU读取执行 - 伪指令
本质上不是指令(只是和指令一起写在代码中),是编译器环境提供的,目的是用来指导编译过程,经过编译后伪指令不会生成机器码
ARM汇编特点
- ldr/str架构
- ARM采用RISC架构,CPU本身不能直接读取内存,而需要先把内存中的内容加载到CPU的通用寄存器中才能被CPU处理
- ldr(load register)指令:将内存中的内容加载入通用寄存器
- str(store register)指令:将寄存器中的内容存入内存空间中
- ldr/str组合用来实现ARM CPU和内存数据交换
- 8种寻址方式
类型 指令 寄存器寻址 mov r1, r2 立即寻址 mov r0, #0XFF00 寄存器移位寻址 mov r0, r1, lsl #3 寄存器间接寻址 mov r1, [r2] 基址变址寻址 mov r1, [r2, #4] 多寄存器寻址 ldmia r1!, {r2-r7, r12} 堆栈寻址 stmfd sp!, {r2-r7, lr} 相对寻址 beq flag
flag: - 指令后缀
同一指令经常附带不同后缀,变成不同的指令含义。如:- B(Byte):功能不变,操作长度变为8位(如:ldr,ldrb)
- H(Half word):功能不变,操作长度变为16位(如:ldr,ldrh)
- S(signed):功能不变,操作数变为有符号(如:ldr,ldrsb,ldrsh)
- S(S标志):功能不变,影响CPSR标志位(如:mov,movs)
- 条件执行后缀
操作码 助记符 标志 含义 0000 EQ Z=1 相等 0001 NE Z=0 不相等 0010 CS/HS C=1 无符号数大于或等于 0011 CC/LO C=0 无符号数小于 0100 MI N=1 负数 0101 PL N=0 正数或0 0110 VS V=1 溢出 0111 VC V=0 没有溢出 1000 HI C=1,Z=0 无符号数大于 1001 LS C=0,Z=1 无符号数小于或等于 1010 GE N=V 有符号数大于或等于 1011 LT N!=V 有符号数小于 1100 GT Z=0,N=V 有符号数大于 1101 LE Z=1,N!=V 有符号数小于或等于 1110 AL 任意 无条件执行(指令默认条件) 1111 NV 任意 从不执行(不要使用) - 多级指令流水线
- 为增加处理器指令流的速度,ARM使用多级流水线
- 运行多个操作同时处理,而非顺序执行
- PC指向正被取指的指令,而非正在执行的指令
ARM常用指令
-
数据处理指令
类别 指令 数据传输指令 mov mvn 算术指令 add sub rsb adc sbc rsc 逻辑指令 and orr eor bic 比较指令 cmp cmn tst teq 乘法指令 mvl mla umull umlal smull smlal 前导零计数 clz -
cpsr访问指令
cpsr寄存器比较特殊,需要专门的指令访问,即:mrs、msr- mrs:读psr
- msr:写psr
-
跳转(分支)指令
指令 描述 b 直接跳转 bl 跳转前把返回地址放入lr中,以便返回,以便于函数调用 bx跳转同时切换到ARM模式,一般用于异常处理的跳转
(现在基本不用了) -
访存指令
指令 描述 ldr/str 单字/半字/字节访问 ldm/stm
(load/store register mutiple)多字批量访问 swp 数据交换 -
软中断指令
- swi(Software interrupt):用来实现操作系统中系统调用
立即数
包括合法立即数、非法立即数
- 合法立即数:经过任意位数的移位后非零部分可以用8位表示
四种栈
- 空栈:
栈指针指向空位,存入时可以直接存入,然后指针移动一格;取出时,需要先移动一格才能取出 - 满栈
栈指针指向栈中最后一格数据,存入时需要先移动指针,再存入;取出时可以直接取出,然后再移动栈指针 - 增栈
栈指针移动时向地址增加的方向移动的栈 - 减栈
栈指针移动时向地址减小的方向移动的栈
八种后缀
- ia(increase after):先传输,再地址+4
- ib(increase before):先地址+4,再传输
- da(decrease after):先传输,再地址-4
- db(decrease before):先地址-4,再传输
- fd(full decrease):满递减堆栈
- ed(empty decrease):空递减堆栈
- fa(full add):满递增堆栈
- ea(empty add):空递增堆栈
特殊符号的作用
- !号作用
如:ldmia r0!, {r2 - r3}
r0的值在ldm过程中发生的增加或减少最后写回到r0,会改变r0的值 - ^号作用
如:ldmfd sp!, {r0 - r6, pc}^
在目标寄存器中有PC时,会同时将spsr写入到cpsr。一般用于从异常模式返回
ARM汇编伪指令
- 伪指令不是指令,和指令的根本区别是:伪指令编译后不会生成机器码
- 伪指令的意义在于:指导编译过程
- 伪指令和具体的编译器相关,使用gnu工具链时,只需学习gnu环境下的汇编指令
gnu汇编中常用符号
符号 | 描述 |
---|---|
@ | 注释。可以在行首,也可以在代码行尾。类似C语言“//” |
# 1 | 注释。行首 |
# 2 | 立即数前面要加#或$,表示立即数 |
: | 以冒号结束的是标号 |
. | 点号在gnu汇编中表示当前指令的地址 |
gnu汇编中常用伪指令
伪指令 | 描述 |
---|---|
.global _start | 给_start外部链接属性 |
.section .text | 指定当前段为代码段 |
.ascii .byte .short .long .word .quad .float .string | 定义数据 |
.align 4 | 以2^4=16字节对齐 |
.balignl 16 0xabcdefgh | 以16字节对齐填充 |
.equ | 类似于C中宏定义 |
.end | 文件的结束 |
.include | 头文件包含 |
.arm / .code32 | 声明为arm指令 |
.thumb / .code16 | 声明为thumb指令 |
nop | 空操作 |
ldr | 大范围的地址加载指令。 伪指令ldr使用,如:ldr r0, =0xff 区别于指令ldr使用,如:ldr r0, #0xff |
adr | 小范围的地址加载指令 |
adrl | 中范围的地址加载指令 |
- adr和ldr的差别
- adr编译时会被一条sub或add指令替代;ldr编译时会被一条mov指令替代或者文字池方式处理
- ldr加载的地址在链接时确定;adr加载的地址在运行时确定
ARM协处理器
协处理器(CP coprocessor)
- 协处理器是SoC内部另一处理核心,协助主CPU实现某些功能,被主CPU调用执行一定任务。
- ARM 设计上支持多大16个协处理器,但一般SOC上只实现其中的CP15
- 协处理器和MMU、cache、TLB等处理有关,功能上和操作系统的虚拟映射、cache管理等有关
协处理器指令
- mrc:读取CP15中的寄存器
- mcr:写入CP15中的寄存器