目录
指令类型:
参数为从目标(destination) 到 源(source);
32未字节码没有后缀,64位常规类型字节码添加-wide后缀;
特殊类型字节码可以添加 -int,-long,-float 等
例:
move-wide/from16 vAA, vBBBB
move为基础字节码(base opcode),表示这是一个基本操作;
-wide为名称后缀(name suffix),表示指令操作的数据宽度(64位);
from16为字节码后缀(opcode sufffix),表示源为一个16位的寄存器引用变量;
vAA为目的寄存器,取值范围为v0~v255;
vBBBB为源寄存器,取值范围为v0~v65535;
空操作指令:
指令 | 解释 |
nop | 值为00,常用于对齐代码 |
数据操作指令:
指令 | 解释 |
move vA, vB | 将vB寄存器的值赋予vA |
move/from16 vAA, vBBBB | 将vBBBB寄存器的值赋给vAA,vBBBB16位,vAA8位。 |
move/16 vAAAA, vBBBB | 将vBBBB寄存器的值赋给vAAAA,均为16位。 |
move-object/from16 vAA, vBBBB | 用于为对象赋值,剩下解释同上 |
move-result-wide vAA | 将上一个invoke类型指令操作的单字非对象结果赋给vAA。 |
move-result-object vAA | 将上一个invoke类型指令操作的对象结果赋给vAA。 |
move-exception vAA | 将一个在运行时发生的异常保存在vAA寄存器中。 |
返回指令:
指令 | 解释 |
return-void | 表示函数从一个void方法返回 |
return vAA | 函数返回一个32位非对象的类型的值,为8位寄存器vAA |
return-wide vAA | 函数返回一个64位非对象的类型的值,为8位寄存器对vAA |
return-object vAA | 函数返回一个对象的类型的值,返回值位为8位寄存器vAA |
数据定义指令:
用于定义程序中用到的常量,字符串,类等数据。
指令 | 解释 |
const/4 vA, #+B | 将数值符号扩展为32位后赋予寄存器vA |
const/16 vAA,#+BBBB | 将数值符号扩展为32位后赋予寄存器vAA |
const vAA,#+BBBBBBBB | 将数值符号赋予寄存器vAA |
const/high16 vAA, #+BBBB0000 | 用于将数值右边的0扩展为32位后赋予寄存器vAA |
const-wide/32 vAA, #+BBBBBBBB | 将数值符号扩展到64位后赋予寄存器对vAA |
const-string vAA, string@BBBB | 通过字符串索引构造一个字符串,并将其赋予寄存器vAA |
const-string/jumbo vAA, string@BBBBBBBB | 通过字符串索引(较大)构造一个字符串,并将其赋予寄存器vAA |
const-class vAA, type@BBBB | 通过类型索引获取一个类引用,并将其赋予寄存器vAA |
因为一个寄存器是32位,所以要先扩展到32位再赋值;-wide表示为64位,故需要两个相邻寄存器组成寄存器对。后面的/4,/16与后面的数值位数有关,一个大写字母表示4位,#+表示后面的是一个常量数字。
锁指令:
指令 | 解释 |
monitor-enter vAA | 为指定对象获取锁 |
monitor-exit vAA | 释放指定对象的锁 |
实例操作指令:
指令 | 解释 |
check-cast vAA, type@BBBB | 将vAA寄存器中的对象引用转化为指定类型,失败会抛出ClassCastException异常 |
instance-of vA, vB, type@CCCC | 判断vB寄存器中的对象引用是否可以转化成指定类型,可以vA=1,否则vA=0 |
new-instance vAA, type@BBBB | 构造一个指定类型对象的新实例,并将对象引用赋值给vAA寄存器。type指定类型不能为数组类 |
check-cast/jumbo vAAAA, type@BBBBBBBB | 与前面指令功能相同,不过指令索引和寄存器取值范围更大。另两个也可加上此后缀 |
数组操作指令:
指令 | 解释 |
array-lengrh vA, vB | 获取vB中数组长度,并将其赋值给vA |
new array vA, vB type@CCCC | 构造指定类型(type@CCCC)和大小(vB)的数组,并将值赋给vA |
filled-new-array {vC, vD, vE, vF, vG}, type@BBBB | 构造指定类型(type@BBBB)和大小(vA)的数组并填充数组内容。vA是隐含使用的,除了指定数组大小还指定了参数的个数 |
filled-new-array/range {vCCCC... vNNNN} | 同上,只是range来指定取值范围,vC是第一个参数寄存器,N=A+C-1 |
fill-array-data vAA, +BBBBBBBB | 用指定的数据填充数组,vAA为数组引用,在指令后面会紧跟一个数据表 |
arrayop vAA, vBB, vCC | 对vBB指定数组元素进行取值和赋值,vCC用于指定数据元素的索引,vAA用于存放需读取或设置的值。读用aget指令,赋值用aput指令;可以加上后缀,如aget-object,aput-wide等 注:蓝色为替换部分 |
异常指令:
指令 | 解释 |
throw vAA | 抛出vAA中指定类型的异常 |
跳转指令:
指令 | 解释 |
goto +AA | 无条件跳转到指定偏移处,偏移量AA不能为0 |
goto/16 +AAAA | 无条件跳转到指定偏移处,偏移量AAAA不能为0 |
packed-switch vAA, +BBBBBBBB | vAA中为switch分支中需要判断的值,BBBBBBBB指向一个packed-switch-payload格式偏移表,表中的值是递增的偏移量。 |
sparse-switch vAA, +BBBBBBBB | vAA中为switch分支中需要判断的值,BBBBBBBB指向一个sparse-switch-payload格式偏移表,表中的值是无规律的偏移量。 |
if-test vA, vB, +CCCC | 比较vA和vB的值,如果满足条件跳转到指定CCCC偏移处,不能为0。其中test可以取以下值: |
if-eq | 相等 if(vA==vB) |
if-ne | 不等 vA!=vB |
if-lt | 小于 vA<vB |
if-le | 小于等于 vA<=vB |
if-gt | 大于 vA>vB |
if-ge | 大于等于 vA>=vB |
if-testz vAA, +BBBB | vAA与0比较,与上面用法一致,就是后面加个z |
if-gtz | 大于0 vAA>0 |
比较指令:
指令 | 解释 |
cmpl-float vAA, vBB, vCC | 比较两个单精度, 如vBB>vCC,vAA=-1; vBB==vCC,vAA=0; vBB<vCC,vAA=1。 |
cmpg-float vAA, vBB, vCC | 比较两个单精度, 如vBB>vCC,vAA=1; vBB==vCC,vAA=0; vBB<vCC,vAA=-1。 |
cmpl-double vAA, vBB, vCC | 比较双精度,其余同上 |
cmpg-double vAA, vBB, vCC | 比较双精度,其余同上 |
cmp-long vAA, vBB, vCC | 比较两个长整数 如vBB>vCC,vAA=1; vBB==vCC,vAA=0; vBB<vCC,vAA=-1。 |
字段操作指令:
普通字段指令前缀为i。
例如:读操作使用iget指令,写操作使用iput指令。
静态字段指令前缀为s。
例如:读操作使用sget指令,写操作使用sput指令。
方法调用指令:
格式:invoke-kind {vC, vD,vE,vF, vG},meth@BBBB
或 invoke-kind/range {vCCCC...vNNNN},meth@BBBB(使用range指定寄存器范围)
指令 | 解释 |
invoke-virtual | 调用实例的虚方法 |
invoke-super | 调用实例的父方法 |
invoke-direct | 调用实例的直接方法 |
invoke-static | 调用实例的静态方法 |
invoke-interface | 调用实例的接口方法 |
方法调用指令必须用move-result* 指令来获取,例:
invoke-static {}, Landroid/os/Parcel;->obtain()Landroid/os/Parcel;
move-result-object v0
数据转换指令:
格式:unop vA,vB
vB中为要转换的数据,转换结果保存在vA或vA寄存器对中。
指令 | 解释 |
neg-int | 对整形求补 |
not-long | 对长整型取反 |
neg-double | 对双精度浮点数求补 |
int-to-char | 将整形转换为字符串 |
int-to-double | 将整形转换为双精度浮点数 |
数据运算指令:
有四类:
1、binop vAA,vBB,vCC vBB与vCC运算,结果保存在vAA中
2、binop/2addr vA,vB vB与vA运算,结果保存在vA中
3、binop/lit16 vA,vB,#+CCCC vB与常量CCCC运算,结果保存在vA中
4、binop/lit8 vAA,vBB,#+CC vBB与常量CC运算,结果保存在vAA中
指令 | 操作 |
add-type | 加法 |
sub | 减法 |
mul | 乘法 |
div | 相除 |
rem | 取模运算(%) |
and | 与运算(AND) |
or | 或运算 |
xor | 异或运算 |
shl | 左移(<<) |
shr | 右移(>>) |
ushr | 无符号数右移 |
这些基础字节码的后面还可加上-type,如:-int,-long,-float等