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-的表示类型值的转换。