Smali中语法:
类型
v void 只能用于返回值类型
Z boolean
B byte
S short
C char
I int
J long 2个寄存器
F float
D double 2个寄存器
对象类型:Lpackage/name/ObjectName; 相当于java中的package.name.ObjectName;解释如下:
L:表示这是一个对象类型
package/name:该对象所在的包
;:表示对象名称的结束
数组的表示形式:
[I :表示一个整形的一维数组,相当于java的int[];
对于多维数组,只要增加[ 就行了,[[I = int[][];注:每一维最多255个;
对象数组的表示形式:
[Ljava/lang/String 表示一个String的对象数组;
方法调用的表示形式:
Lpackage/name/ObjectName;——>methodName(III)Z 详解如下:
Lpackage/name/ObjectName 表示类型
methodName 表示方法名
III 表示参数(这里表示为3个整型参数)
说明:方法的参数是一个接一个的,中间没有隔开;
method(I [[I I Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
method(int,int[][],int,String,Object[])
在java中则为:
String method(int, int[][], int, String, Object[])
字段的表示形式:
Lpackage/name/ObjectName;——>FieldName:Ljava/lang/String;
即表示: 包名,字段名和各字段类型
有两种方式指定一个方法中有多少寄存器是可用的:
.registers 指令指定了方法中寄存器的总数
.locals 指令表明了方法中非参寄存器的总数,出现在方法中的第一行
方法的传参:
当一个方法被调用的时候,方法的参数被置于最后N个寄存器中。如果一个方法有2个参数,5个寄存器(v0-v4),那么参数将置于最后2个寄存器——v3和v4。 非静态方法中的第一个参数总是调用该方法的对象。
例如,非静态方法LMyObject;->callMe(II)V有2个整型参数,另外还有一个隐含的LMyObject;参数,所以总共有3个参数。假如在该方法中指定了5个寄存器(v0-v4),以.registers方式指定5个或以.locals方式指定2个(即2个local寄存器+3个参数寄存器)。当该方法被调用的时候,调用该方法的对象(即this引用)存放在v2中,第一个整型参数存放在v3中,第二个整型参数存放在v4中。
寄存器的命名方式:
V命名
P命名 第一个寄存器就是方法中的第一个参数寄存器
比较:使用P命名是为了防止以后如果在方法中增加寄存器,需要对参数寄存器重新进行编号的缺点
特别说明一下:Long和Double类型是64位的,需要2个寄存器
例如:对于非静态方法
LMyObject——>myMethod(IJZ)V;
有4个参数:LMyObject,int,long,bool; 需要5个寄存器来存储参数;
P0 this
P1 I (int)
P2,P3 J (long)
P4 Z(bool)
补充:
@ static fields 定义静态变量的标记
@ instance fields 定义实例变量的标记
@ direct methods 定义静态方法的标记
@virtual methods 定义非静态方法的标记
构造函数的返回类型为V,名字为<init>。
if-eq p1, v0, :cond8 表示如果p1和v0相等,则执行cond8的流程:
:cond8
invoke-direct {p0}, Lcom/paul/test/a;->d()V
调用com.paul.test.a的d()方法
if-ne p1, v0, :condb 表示不相等则执行condb的流程:
:condb
invoke-direct {p0}, Lcom/paul/test/a;->c()V