arm64 指令个人记录
- ARM指令集是指计算机ARM操作指令系统。在ARM中有两种方式可以实现程序的跳转:一种是跳转指令;另一种是直接向PC寄存器(R15)中写入目标地址值。
- ARM指令集可以分为数据处理指令,数据加载指令和存储指令,分支指令,程序状态寄存器(PSR)处理指令,协处理器指令和异常产生指令六大类。
arm指令
指令 | 作用 |
---|---|
ADC | 带进位的32位数加法 |
ADD | 32位数相加 |
SUB | 32位减法 |
AND | 32位数的逻辑与 |
B | 在32M空间内的相对跳转指令 |
BKPT | 断点指令 |
BL | 带链接的相对跳转指令-(1) 将下一条指令的地址放入lr(x30)寄存器,(2)转到标号出执行指令 |
BLX | 带链接的切换跳转 |
BX | 切换跳转 |
BEQ | 相等则跳转(Branch if EQual) |
BNE | 不相等则跳转(Branch if Not Equal) |
BGE | 大于或等于跳转(Branch if Greater than or Equa) |
BGT | 大于跳转(Branch if Greater Than) |
BIC | 32位数的逻辑位清零 |
RET | 默认使用lr(x30)寄存器的值通过底层指令提示CPU此处作为下条指令地址(ARM64平台的特色指令,面向硬件做了优化处理) |
BLE | 小于或等于跳转(Branch if Less than or Equal) |
BLEQ | 带链接等于跳转(Branch with Link if EQual) |
BLLT | 带链接小于跳转(Branch with Link if Less Than) |
BLTt | 小于跳转(Branch if Less Than) |
CDP CDP2 | 协处理器数据处理操作 |
CLZ | 零计数 |
CMN | 比较两个数的相反数 |
CMP | 32位数比较 |
EOR | 32位逻辑异或 |
LDC LDC2 | 从协处理器取一个或多个32位值 |
LDM | 从内存送多个32位字到ARM寄存器 |
STUR | 把寄存器的值(32位)存到一个内存的虚地址内间(一般等同str) |
STR | 把寄存器的值(128位/64位)存到一个内存的虚地址内间 |
LDP | str的变种,可以同时操作两个寄存器 |
LDR(load register) | 从内存地址取一个单个的32位值加载入通用寄存器 |
STD | ldr的变种,可以同时操作两个寄存器 |
DLP(load register) | 从内存地址取一个单个的64位值加载入通用寄存器 |
MCR MCR2 MCRR | 从寄存器送数据到协处理器 |
MLA | 32位乘累加 |
MOV | 传送一个32位数到寄存器 |
MRC MRC2 MRRC | 从协处理器传送数据到寄存器 |
MRS | 把状态寄存器的值送到通用寄存器 |
MSR | 把通用寄存器的值传送到状态寄存器 |
MUL | 32位乘 |
MVN | 把一个32位数的逻辑“非”送到寄存器 |
ORR | 32位逻辑或 |
PLD | 预装载提示指令 |
QADD | 有符号32位饱和加 |
QDADD | 有符号双32位饱和加 |
QSUB | 有符号32位饱和减 |
QDSUB | 有符号双32位饱和减 |
RSB | 逆向32位减法 |
RSC | 带进位的逆向32法减法 |
SBC | 带进位的32位减法 |
SMLAxy | 有符号乘累加(16位*16位)+32位=32位 |
SMLAL | 64位有符号乘累加((32位*32位)+64位=64位) |
SMALxy | 64位有符号乘累加((32位*32位)+64位=64位) |
SMLAWy | 号乘累加((32位*16位)>>16位)+32位=32位 |
SMULL | 64位有符号乘累加(32位*32位)=64位 |
SMULxy | 有符号乘(16位*16位=32位) |
SMULWy | 有符号乘(32位*16位>>16位=32位) |
STC STC2 | 从协处理器中把一个或多个32位值存到内存 |
STM | 把多个32位的寄存器值存放到内存 |
SWI | 软中断 |
SWP | 把一个字或者一个字节和一个寄存器值交换 |
TEQ | 等值测试 |
TST | 位测试 |
UMLAL | 64位无符号乘累加((32位*32位)+64位=64位) |
UMULL | 64位无符号乘累加(32位*32位)=64位 |
B.LE | 标号:小于等于(if判断) |
B.LT | 标号:小于等于(do while) |
B.GT | 标号:小于等于(while do) |
B.GE | 标号:大于等于(for) |
B.EQ | 标号:比较结果是等于,执行标号,否则不跳转 |
B.HI | 标号:比较结果是无符号大于,执行标号,否则不跳转 |
跳转指令
通过直接向PC寄存器中写入目标地址值可以实现在4GB地址空间中任意跳转,这种跳转指令又称为长跳转。如果在长跳转指令之前使用MOV LR,PC等指令,则可以保存将来返回的地址值,这样就实现了在4GB地址空间中的子程序调用。
在ARM版本5及以上的体系中,实现了ARM指令集和Thumb指令集的混合使用。指令使用目标地址值的bit[0]来确定目标程序的类型。bit[0]的值为1时,目标程序为Thumb指令;bit[0]值为0时,目标程序为ARM指令。
在ARM版本5以前的体系中,传送到PC寄存器中的目标地址值的低两位bits[1∶0]被忽略,跳转指令只能在ARM指令集中执行,即程序不能从ARM状态切换到Thumb状态。非T系列ARM版本5体系不含Thumb指令,当程序试图切换到Thumb状态时,将产生未定义指令异常中断。
ARM跳转指令可以从当前指令向前或向后的32MB地址空间跳转。这类跳转指令有以下4种。
(1)B 跳转指令
B〔条件) (地址)
- B指令属于ARM指令集,是最简单的分支指令。一旦遇到一个B指令,ARM处理器将立即跳转到给定的地址,从那里继续执行。注意:存储在分支指令中的实际值是相对当前R15的值的一个偏移量,而不是一个绝对地址。它的值由汇编器来计算,是24位有符号数,左移两位后有符号扩展为32位,表示的有效偏移位为26位(+/- 32 MB)。
(2)BL 带返回的跳转指令
BI,〔条件) (地址)
- BL指令也属于ARM指令集,是另一个分支指令。就在分支之前,在寄存器R14中装载上R15的内容,因此可以重新装载R14到R15中来返回到这个分支之后的那个指令处执行,它是子例程的一个基本但强力的实现。
(3)BLX 带返回和状态切换的跳转指令
BLX <地址>
BLX指令有两种格式
- 第1种格式的BLX指令记作BLX(1)。BLX(1)从ARM指令集跳转到指令中指定的目标地址,并将程序状态切换到Thumb状态,该指令同时将PC寄存器的内容复制到LR寄存器中。
BLX(1)指令属于无条件执行的指令。
- 第2种格式的BLX指令记作BLX(2)。BLX(2)指令从ARM指令集跳转到指令中指定的目标地址,目标地址的指令可以是ARM指令,也可以是Thumb指令。目标地址放在指令中的寄存器<dest>中,该地址的bit[0]值为0,目标地址处的指令类型由CPSR中的T位决定。该指令同时将PC寄存器的内容复制到LR寄存器中。
(4)BX 带状态切换的跳转指令
BX(条件) (dest)
- BX指令跳转到指令中指定的目标地址,目标地址处的指令可以是ARM指令,也可以是Thumb指令。目标地址值为指令的值和0xFFFFFFFE做“与”操作的结果,目标地址处的指令类型由寄存器决定。
常见汇编代码解读
add w0, #0xa ;w0中的值加0xa(10)
CMP W0, W1 ;比较大小 == SUB W0,W0,W1 不同CMP指令不改变w0的值
str w10 [sp] ; 注: 其中[]表示取sp地址;整句的意思是将读取w10中数据并存放到栈内
std x29, x30,[sp, #-0x10] == ( sub sp, sp,#0x10 std x29,x30, [sp] )
ldp x29,x30,[sp],#0x10 == ldp x29,x30,[sp] add sp,sp,#0x10
orr
adrp x0 , 1 ;注释下面
- 将1的值,左移12位 1 0000 0000 0000 == 0x1000
- 2.将PC寄存器的低12位清零0x104bee870 ==> 0x104bee000,这里的PC寄存器的值是到adrp x0 1的那里的PC寄存器里面的值
- 3.将1 和 2 的结果相加给X0 寄存器!!pc寄存器低32位清零左移1位
寄存器作用
- w0 - w7 存储函数传入的参数 如果参数超过8个会对超出的参数做入栈操作
- w0 一般会保存返回值
- x29 没有什么特殊作用
- x30 作用:保护回家的路 - ret 指令 返回x30中保存的指令地址
- CPSR 寄存器
- N:负数标志位。如果目标寄存器中的有符号数为负数,则N=1,否则N=0。
- Z:零标志位。如果目标寄存器中的数为0,则N=1,否则N=1。
- C:进位标志位。有以下3种情况
1、无符号加法运算和CMN指令,如果产生进位,则C=1,否则C=0;
2、无符号减法运算和CMP指令,如果产生借位,则C=0,否则C=1;
3、进行移位操作的时候,C中保存最后一位移出的值。
说明:当一条指令中同时含有算术运算指令和移位指令时,影响C的值是算术运算而不是移位操作。- V:溢出标志位。进行有符号运算时如果发生错误,则V=1,否则V=0。
一些指令如CMN、TEQ等会无条件的刷新CPSR中的条件标志位,其他指令必须要在指令后面加上S后缀才会改变CPSR中的条件标志位。
- I:IRQ中断禁止位。I=1代表禁止IRQ中断,I=0代表允许IRQ中断。
- F:FIQ中断禁止位。F=1代表禁止FIQ中断,F=0代表允许FIQ中断。
这里和51单片机中的中断使能位有点小差别,51中的是中断使能位,所以为1的时候应该是中断使能,即允许中断。而这里是中断禁止位,为1的时候应该是禁止中断。- T:这一位只在ARMv4T指令集版本及以上才有效。因为ARMv4版本及以下都不支持Thumb指令集。在支持Thumb指令集的处理器中,T=0表示处于ARM状态,T=1表示处于Thumb状态。
- M[4:0]:用于控制7种模式位(用户模式(usr)、系统模式(sys)、快速中断模式(fiq)、中断模式(irq)、中止模式(abt)、未定义指令模式(und)、管理模式(svc))。
上述的7中处理器模式中,还可分类为特权模式,异常模式。
- 特权模式:除了用户模式之外的所有模式都是特权模式。在其他模式下都可以修改模式位来切换至不同的模式,而用户模式下不允许修改模式位。特权模式下可以比用户模式访问到更多的系统资源。
- 异常模式:除了用户模式和系统模式之外的所有模式都是异常模式。