前言
前言不罗嗦了,接上一篇回顾arm汇编寄存器、指令详解。
上一篇传送门
一、ARM寄存器
其实寄存器我在ARM汇编基础回顾----ARM基本概念中有过一些记录介绍,这里作补充添加。
寄存器 | 用途 |
---|---|
R0 | 通用寄存器 |
R1 | 通用寄存器 |
R2 | 通用寄存器 |
R3 | 通用寄存器 |
R4 | 通用寄存器 |
R5 | 通用寄存器 |
R6 | 通用寄存器 |
R7 | 一般放系统调用号 |
R8 | 通用寄存器 |
R9 | 通用寄存器 |
R10 | 通用寄存器 |
R11(fp) | 栈帧指针 |
R12(ip) | 内部程序调用 |
R13(sp) | 栈指针 |
R14(lp \ lr) | 链接寄存器(一般存放函数返回地址) \ 程序计数器or机器码指针 |
R15(pc) | 程序计数寄存器 |
CPSR | 当前程序状态寄存器 |
PS:不同模式下访问的寄存器组不尽相同,SPSR寄存器是CPSR的备份,详情请看ARM汇编基础回顾----ARM基本概念
以下是ARM架构寄存器与Intel架构寄存器的对照关系:
ARM 描述 X86
--------------------------------------------------------------
R0 通用寄存器 EAX
R1-R5 通用寄存器 EBX,ECX,EDX,ESI,EDI
R6-R10 通用寄存器 -
R11(fp) 栈帧指针 EBP
R12 内部程序调用 -
R13(sp) 栈指针 ESP
R14(lp) 链接寄存器 -
R14(lr) <-程序计数器/机器码指针-> EIP
CPSR 程序状态寄存器 EFLAGS
ARM寄存器详解:
r0~r3 主要用于子程序间传递参数(在ARM的函数调用约定中,前四个参数按顺序存放在R0-R3中)。
r4~r11主要用于保存局部变量,在Thumb 程序中,通常只能使用 r4~r7 来保存局部变量。
r12 用作子程序间指令指针寄存器,即ip 寄存器。
r13 栈指针寄存器(sp)。用来指向当前的栈顶。栈是一片来存储函数调用中相关数据的内存,在函数返回时会被修改为对应的栈指针。栈指针用来帮助在栈上申请数据空间。比如说申请一个字的大小,就会将栈指针减4,再将数据放入之前所指向的位置。
r14 寄存器又被称为连接寄存器(lr),用于保存子程序以及中断的返回地址。当一个函数调用发生,链接寄存器就被用来记录函数调用发生所在位置的下一条指令的地址。这么做可快速的从子函数返回到父函数。
r15 用作程序计数器(pc),程序计数器是一个在程序指令执行时自增的计数器。它的大小在ARM模式下总是4字节对齐,在Thumb模式下总是两字节对齐。当执行一个分支指令时,PC存储目的地址。在程序执行中,ARM模式下的PC存储着当前指令加8(两条ARM指令后)的位置,Thumb(v1)模式下的PC存储着当前指令加4(两条Thumb指令后)的位置。这也是X86与ARM在PC上的主要不同之处。
CPSR和SPSR都是程序状态寄存器,其中SPSR是用来保存中断前的CPSR中的值,以便在中断返回之后恢复处理器程序状态。
*当前程序状态寄存器CPSR
所有处理器模式下都可访问CPSR。CPSR中包含条件码标志、中断禁止位、当前处理器模式以及其他状态和控制信息。在每种异常模式下都有一个对用的程序状态寄存器SPSR。当异常出现时,SPSR用于保存CPSR的状态,以便异常返回后恢复异常发生时的工作状态。
上两张图展示32位的CPSR寄存器的比特位含义,左边是最大比特位,右边是最小比特位。每个单元代表一个bit。以下为图中标记的含义。
标记 | 含义 |
---|---|
N(Negative) | 指令结果为负值时置1 |
Z(Zero) | 指令结果为零值时置1 |
C(Carry) | 对于加法有进位则置1,对于减法有借位则置0 |
V(Overflow) | 指令结果不能用32位的二进制补码存储,即发生了溢出时置1 |
E(Endian) | 小端序置0,大端序置1 |
T(Thumb) | 当为Thumb模式时置1,ARM模式置0 |
M(Mode) | 当前的权限模式(用户态,内核态) |
J(Jazelle) | 允许ARM处理器去以硬件执行java字节码的状态标示 |
二、ARM指令
ARM指令模板
MNEMONIC{S}{condition} {Rd}, Operand1, Operand2
助记符{是否使用CPSR}{是否条件执行以及条件} {目的寄存器}, 操作符1, 操作符2
ARM指令有以下几类:
1)分支跳转指令
2)数据处理指令
3)乘法指令
4)乘加指令
5)状态寄存器访问指令
6)单寄存器加载存储指令
7)多寄存器加载存储指令
8)异常产生指令
9)协处理器指令
10)信号量指令
11)其他扩展指令
下面详解ARM指令(部分重要指令)
1. 分支跳转指令
先了解一下ARM跳转方式:
1)发生异常
2)使用分支指令
3)直接向PC赋值
B: goto
BL:跳转之前自动记录下条指令的地址到LR 用于函数调用
语法格式:
B{
L}{
COND}<target>
B 类似goto
L 跳转前 硬件自动将下条指令地址记录到LR
COND 该指令可以条件执行
target 目标地址
b/bl跳不了很远,只能往前或往后跳32M,它属于地址无关码
编译.so -fpic ,链接地址和运行地址要保持一致
BX
BLX
语法格式:
B{
L}X{
COND}<Rm>
X 带状态切换的分支跳转指令
COND 该指令可以条件执行
Rm 通用寄存器,其中存储了要跳转的目标地址
bx/blx跳转范围不受限(0~4G),属于地址相关码
2. 数据处理指令
2.1 移位操作
LSL: 逻辑左移
LSR: 逻辑右移
ASR: 最高位补符号位,等价于C语言中的 >>
ROR: 循环右移
2.2 数据传输指令
MOV{
COND}{
S} <Rd>, <operand>
cond 指令可以条件执行
s 操作结果影响CPSR NZC位
mov r0, #11 @r0=11
movs r0, #11 @r0=11
@N=Rd[31]
@if(Rd==0) Z=1 else Z=0
Rd 目标寄存器 一定是通用寄存器
operand
立即数
mov r0, #11
moveqs r0, #11 @if(相等){
movs r0, #11}
注意:立即数的合法性问题
该立即数可以通过一个8bit立即数循环右移偶数位得到,那么就是合法的
如 mov r0, #0x1ff @不合法
寄存器
mov r0, r1 @r0=r1
寄存器移位之后的值
mov, r0, r1, lsl #3 @r0=r1*8
MVN{
COND