1.1smali语言基础语法-数据类型和描述符
smali里面有两种数据类型:
1).基本类型
2).引用类型------》1.对象类型,2.数组类型
对象类型表示形式: L 包名/对象名; L packagename/ObjectName;
packagename 使用”/“代替”.“
ObjectName是对象的名称;
分号表示对象的结束;
数组类型:
以 '['数据类型 加上类型描述符 的形式表示;
比如:
[ I 表示一维整型数组
[[ I 表示二维数组
[L java/lang/String 表示String数组
字段的描述
Davilk中对字段的描述分为两种,对基本类型字段的描述和对引用类型的描述,但是两者的描述格式一样:
对象类型类型描述符→字段名 : 类型描述符;
例如com.bluesson.Test类中存在String类型的name字段以及int类型的age字段,那么其描述为:
Lcom/bluesson/Test; →name:Ljava/lang/String;
Lcom/bluesson/Test;-→age:I
方法的描述
对象类型描述符-→方法名(参数类型描述符) 返回值类型描述符
下面以java.lang.String为例:
java方法: public char charAt(int index){… …}
Davilk描述: L java/lang/String; -→charAt(I) C
java方法: public void getChars(int srcBeg, int srcEnd ,char dst[],int dstBegin){…}
Davilk描述: L java/lang/String;-→getChars(I I [C I)V
java方法: public boolean equals(Object anObject){…}
Davilk描述:Ljava/lang/String;–→equals(L java/lang/Object;)Z
1.2 寄存器以及传参,局部变量
在smali汇编中,寄存器都是32位的,能够支持任何类型;64位类型(long和Double)用两个寄存器表示;
指定一个方法中有多少个寄存器有两个方法:
-
.registers指令指定了方法中寄存器的总数;
-
locals 指令表明了方法中非参寄存器的数量;
方法中使用寄存器传参的默认规则:
1.当一个方法被调用的时候,方法的参数被设置于最后N个寄存器.如果一个方法有两个参数,5个寄存器(v0-v4),那么参数将置于最后两个寄存器v3和v4;
2.非静态方法中的第一个参数总是调用该方法的对象;
eg:LMyObject;-→callMe (II) V
这里有2个整型参数,另外还有一个隐含的LMyobject参数,所以总共有3个参数.如果该方法中指定了5个寄存器(v0-v4),以.registers方式指定5个或者以.local方式指定2个(2个local寄存器+3个参数寄存器)。当该方法被调用的时候,调用该方法的对象(this引用)存放在v2中,第一个整型参数存放于v3中,第二个整型参数存放于v4里面;
而静态方法除了没有隐含的this参数以外其他都一样;
寄存器的命名方式有两种:
1.V命名方式
2.P命名方式
P命名方式中的第一个寄存器就是方法中的第一个参数寄存器;
下表表示了上个例子中的5个寄存器和3个参数的两种命名方法:
注意:baksmali默认对参数寄存器使用P命名方式;
下面看一个例子(java源码):
public void callMe(int a,int b){
System.out.println(a + b);
}
反编译之后的smali汇编代码:
.method public callMe(II)V
.locals 2 #定义局部变量寄存器,
.param p1 , "a" # I 声明参数
.param p2 , "b" #I
.prologue #代码起始处
.line 20 #源代码所在行数
#获取out对象
sget-object v0, Ljava/lang/System;--→out:Ljava/io/PrintStream;
#out是属于 Ljava/lang/System类的;将out这个对象放于v0里面;
#将参数累加
add-int v1,p1,p2
#输出信息
invoke-virtual {v0,v1}, Ljava/io/PrintStream;→printIn(I)V
.Line 21
return-void
.end method
关于Long和Double值
Long和double类型是64位的,需要两个寄存器(切记)
对于非静态方法LMyobJect;-→MyMethod(IJZ)V,参数分别是LMyobject;,int,long,bool.故该方法至少需要5个寄存器来存储:
再看一个例子: (先看源码)
pubic void MyMethod(int a,long c,int b){
System.out.println(a+ c + b);
}
分析smali代码:
.method public Mymethod(IJI)V
.locals 6 #定义局部变量寄存器,总共v0,this,I,J(两个寄存器),Z
.param p1 , "a" # I 声明参数
.param p2 , "c" #J
.param p24, "b" #I
.prologue #代码起始处
.line 24 #源代码所在行数
sget-object v0,Ljava/lang/System;→out:Ljava/io/PrintStream;
int-to-long v2,p1
#v2 = v2+p2 v3 = v3+p3
# int-to-long vx, vy
#转换Vy寄存器中的Int型值存入Vx,Vx+1,这里有两个寄存器
add-long/2addr v2,p2
int-to-long v4,p4
#v2 = v2+v4 v3 = v3+v5
add-long/2addr v2,v4
.line 25
return-void
.end method