Smali指令查询白皮书

1.反编译apk高频出现指令

const/4 v1, #int 2 表示存入int型常量2到v1,目的寄存器在第二个自己的低4位,常量2在更高的4位。
const/16 v0, #int 10 表示存入int型常量10到v0中。
move-object/from16 v1, v21 表示将v21寄存器中的对象引用到v1上。
heck-cast v4 Test3 检查v4寄存器中的对象引用是否可以转换为Test3的实例。
Instance-of v0, v4, Test3 检查V4寄存器中的对象引用是否是Test3的实例,如果是V0存入非0值,否则v0存入0。
array-length v0, v1 计算v1寄存器中数组引用的元素长度并将长度存入V0。
cmpl-float v0, v6, v7 比较v6和v7的float值,并在v0存入int型的返回值。非数值默认为小于,如果参数为非数值将返回-1。
cmpg-float v0, v6, v7 比较v6和v7的float值,并在v0存入int型的返回值。非数值默认为大于,如果参数为非数值将返回1。
age v7,v3,v6 从数组获取一个int型值到v7,对象数组的引用位于v3,需获取的元素的索引位于v6。
age-byte v0, v0, v1 从byte数组获取一个byte值到v0,数组的引用位于v0,徐获取的元素的的索引位于v1。
aput v0, v3, v5 将v0的int值作为元素存入int数组,数组的引用位于v3,元素的索引位于v5。
move-result v0 移动上一次方法调用的返回值到v0。
move-result-wide v2 移动上一次方法调用的long/double型返回值到v2,v3。
new-array v4, v2, [Ljava/lang/Object; 新建一个Object数组,v2存入数组的长度,v4存入数组的引用。
invoke-virtual{v4,v0,v1,v2,v3}, Test.method:(IIII)V 表示调用Test的method方法,该指令共有5个参数,参数v4是this实例,v0,v1, v2,v3 是method方法的参数,返回值为Void
sput-object v0, test3.os1:Ljava/lang/object 将v0寄存器中的对象引用赋值到Test3的对象引用静态字段os1上。
iget-object v1,v2, LineReader.fis:Ljava/io/FileInputStream 读取FileInputStream对象引用字段fis到v1,v2寄存器中是LineReader实例的引用。
invoke-direct, java.lang.object.:()V 表示java.lang.object 的方法,参数v1是this的实例,()V表示方法没有参数,v是返回值为void。
intvoke-direct{0}, Landroid/app/TabActivity;->()v 这里init()就是定义TabActivity中的一个private函数。
iput-object v0, v2,LineRader.bis:Ljava/io/BufferedInputStream 将V0寄存器的值存入实例的对象引用字段bis,v2寄存器中是BufferedInputStream实例的引用。
rem-int v0 v2,v3 计算v3%v2并将结果存入v0
add-int/lit8 v0, v0, 0x1 表示 v0++的意思

2.高频的结构

.method public constructor ()V #这是class的构造函数实现。
.registers 1 #这个方法所使用的寄存器数量。
invoke-direct {p0}, Ljava/lang/Object;->()V #调用Object的构造方法,p0相当于"this" 指针。
invoke-virtual {p0}, Ljava/lang/Object;->toString()Ljava/lang/String;#调用toString()函数。 new-instance v5, Ljava/lang/StringBuilder; 表示新建一个临时的StringBuilder对象,并将其引用赋值给v5寄存器。
invoke-direct {v1}, Ljava/lang/StringBuilder;->()V 调用stringBuilder中的构造方法。
invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; 表示{v1, v2}大括号中v1寄存器中存储的是StringBuilder对象的引用,调用StringBuilder中的append(String, str)方法,v2寄存器则是参数寄存器。


附:

内部类格式:外部类外部类内部类.smali,如果是匿名的内部类那么格式:外部类外部类内部类.smali ,如果是匿名的内部类那么格式:外部类外部类内部类.smali,如果是匿名的内部类那么格式:外部类外部类NUM.smali。其中NUM代表从1开的数字。 对于Java文件中的每一个内部类,都会产生一个单独的smali文件,比如ActivityThread1.smali。这些文件的命名规范是如果是匿名内部类,则命名规则是外部类+1.smali。这些文件的命名规范是如果是匿名内部类,则命名规则是外部类+1.smali。这些文件的命名规范是如果是匿名内部类,则命名规则是外部类++数字,否则的话是外部类++内部类的名字例如:classOuterclassInner反编译上述代码后会生成两个文件:Outer.smali与Outer+内部类的名字 例如: class Outer { class Inner{} } 反编译上述代码后会生成两个文件:Outer.smali 与Outer+内部类的名字例如:classOuterclassInner反编译上述代码后会生成两个文件:Outer.smali与OuterInner.smali

静态方法中没有this指针,也就是p0不再是this指针,而是第一个参数,非静态方法p0表示this指针。
invoke-virtual {p0} 这个p0就是this参数:
invoke-virtual {p0}, Lcom/nd/tq/NDSecDataType;->toString()Ljava/lang/String; 这个表示 NDSecDataTyep.toString()
invoke-static {p1} 这个p1表示具体的参数非this。
invoke-static {p1}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I 表示 Integer.parseInt(p1)

long和double型的值占用两个寄存器。例如:一个在v0寄存器的double值实际占用V0、v1两个寄存器。

boolean的值实际是转成int型的值进行操作,存储实际是1和0.

mov-object vx,vy:移动对象引用,从vy到vx。
mov-result-wide vx 移动上一次方法调用的long/double型返回值到vx,vx+1。
const-class vx,类型ID:存入类对象常量到vx,通过类型id或类型例如:const-class v0,test3 表示存入test3.class的引用到v0。
check-cast vx,类型ID:检查vx寄存器中的对象引用是否可以转换城类型ID对应类型的实例。 如不可转换,抛出ClassCastException异常,否则继续执行。
check-cast vx4,test3 检查v4寄存器中的对象引用是否可以转换为test3的实例
new-array vx,vy 根据类型id或者类型新建一个数组,vy存入数组的长度,vx存入数组的引用

age开头的都跟数组获取有关系的 比如: aget vx,vy,vz 从int数组获取一个int型值到vx中,其中对象数组引用是vy,数组元素索引是vzage后面-跟的条件 只不过是获取值的对一个条件,比如 aget-object vx,vy,xz 表示的是从对象引用数组获取一个对象引用到vx,对象数组的的引用位于vy获取元素的索引位于vz。

aput开头的都跟数组存入有关系的的 比如: aput vx,vy,vz 表示将vx的int值作为元素存入int数组,数组的引用位于vy,元素的索引位于vz。

iget开头的对寄存器实例引用的赋值 比如: iget vx,vy,字段ID 根据字段ID读取实例的int型字段到vx,vy寄存器中是该实例的引用,例如: iget v0,v1 test2.i6:I表示读取int型字段i6到v0中,其中v1寄存器是test2实例的引用。iput开头的是将寄存器的值存入实例中:比如 iput vx,vy,字段ID 根据字段ID将Vx寄存器的值存入实例的int型字段,vy寄存器是该实例的引用。例如: iput v0,v2 test2.i6:I 将v0寄存器的值存入实例的int型字段i6,v2寄存器中是test2实例的引用。

sget开头的是读取静态相关字段信息 sget vx 字段ID 根据字段ID读取静态int型字段到vx sput开头的是将寄存器的值赋值到静态字段中。例如: sput vx,字段id 根据字段ID将vx寄存器中的值赋值到int型静态字段。

neg开头的表示相减的neg后面跟的是类型和寄存器 neg-int vx,vy 计算vx= -vy并将结果存入vx。

int-to-long vx,vy 转换vy寄存器中的int型值为long型值存入vx,vx+1 其中字段中间有个-to-的表示类型值的转换。

转载zhuanlan.zhihu.com/p/609972000

相关推荐
yuanbenshidiaos14 小时前
c++---------数据类型
java·jvm·c++
java1234_小锋16 小时前
JVM对象分配内存如何保证线程安全?
jvm
40岁的系统架构师20 小时前
1 JVM JDK JRE之间的区别以及使用字节码的好处
java·jvm·python
寻找沙漠的人20 小时前
理解JVM
java·jvm·java-ee
我叫啥都行20 小时前
计算机基础复习12.22
java·jvm·redis·后端·mysql
bufanjun0011 天前
JUC并发工具---ThreadLocal
java·jvm·面试·并发·并发基础
东阳马生架构1 天前
JVM简介—1.Java内存区域
jvm
工程师老罗1 天前
Android笔试面试题AI答之SQLite(2)
android·jvm·sqlite
Qzer_4072 天前
jvm字节码中方法的结构
jvm
奇偶变不变2 天前
RTOS之事件集
java·linux·jvm·单片机·算法