您的位置:首页 > 移动开发 > Android开发

Android smali 语法三

2016-04-29 21:15 477 查看
在上篇博文的动手实践中,我们将.java文件转化成.smali文件后,发现java中的数据类型、域名、方法名在.smali文件中发生了改变。事实上,当.java文件被javac、dx工具转换成Dalvik VM可执行文件.dex后,数据类型、域名、方法名就已经发生了变化。.smali文件和.dex文件中数据类型、域名、方法名是相同的,所以我们看一下.dex文件中数据类型、域名、方法名就行了。

一、数据类型

.dex文件中存储的是Dalvik VM运行的字节码,字节码有两种主要的数据类型:基本数据类型(primitive types)和引用类型。引用类型由数组和对象组成,其它的全是基本数据类型。

基本类型由一个字母表示,事实上这些缩写的字母在.dex文件中以string形式存储。他们在 dex-format.html document文件(dalvik/docs/dex-foramt.html in the AOSP repository)中进行了定义

基本数据类型

Dalvik/smaliJava
Vvoid-can only be used for return types
Zboolean
Bbyte
Cchar
Iint
Jlong(64bits)
Ffloat
Ddouble(b4bits)
对象的命名格式为:Lpackage/name/ObjectName; ——– L 表示它是对象, package/name/ 是对象所在的包,ObjectName 表示对象。该命名格式等价Java中 package.name.ObjectName。例如 Ljava/lang/String;等价于java.lang.String

数组的命名格式为:[I ——- 它表示一个int类型的一维数组,如果表示多维数组,者加[字符,例如:[[i=int [][] , [[[i=int[][][].

对象数组: [Ljava/lang/String;

二、方法

方法的定义是比较冗长的,通常包括方法名、参数类型、和返回类型。这些信息确保Dalvik VM能够正确的找到方法运行和对字节码进行进行静态分析。方法的格式:

Lpackage/name/ObjectName;->MethodName(III)Z

其中MethodName 是方法名,(III) 是方法的签名,Z是返回类型

例子:method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/string等价于String method(int,int[][],int,String,Object)

三、域

域名的定义也是冗长的,通常包括作用域、域名、域的类型

域的格式:

Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;

四、科普:smali方法中的寄存器

为了给下篇的java方法中代码转化成 .smali文件方法中的指令做铺垫 ,我们在这里科普一下Dalvik 字节码中的寄存器

在davilk字节码中,寄存器总是32位的并且可以存储任何类型的值。2 个寄存器用来存储64位的类型(Long and Double)

1.在方法中定义寄存器的数量

在方法中有两种方式定义方法中可以使用的寄存器数量。.registers 指令定义了方法中可以使用的寄存器的总数量。可以选择性的使用.locals ,该指令定义了方法中非参数寄存器的数量。寄存器的总数量应当包括方法参数所使用的寄存器的数量

2.方法参数传递给方法的方式

当方法被调用时,传递给方法的参数被保存在最后的n个寄存器中。如果一个方法有2个参数和5个寄存器(v0-v4),那么参数将被放在最后两个寄存器中(v3和v4中)。

对于一个非静态方法来说,传递给它的第一个参数总是方法被调用的对象本身 。例如,假设你写了一个非静态的方法LMyObject;->callMe(II)V。这个方法有2个integer类型的参数,但是在这两个integer类型参数之前它也有一个隐含的参数LMyObject;,所以该方法总 共有3个参数。再例如,假设在方法中(v0-v5)定义了5个寄存器—由.register 5指令或者.locals 2指令( 2 local register + 3 parameter register)定义。当该方法被调用时,该对象(the this reference )会被放在v2寄存器中,第1个integer参数会被放在v3中,第2个integer参数会被放在v4中。

静态方法不会有隐含的this参数,其它的参数存放方法与非静态的方法参数存放方法一样。

3.寄存器的命名

寄存器命名有两种方案:v字命名法和p字命名法。

v字命名p字命名说明
v0the first local register
v1the sencond local register
v2lp0the first paramter register
v3p1the second parameter register
v4p2the third parameter register

4.介绍参数寄存器(parameter)的原因

由于方法参数是保存在最后n个寄存器的,如果用 v 字命名法,修改smail 文件的寄存器总个数后,每个保存参数的寄存器序号仍旧需要修改。而使用 p 字命名法,则不需要保存参数的寄存器序号,比较方便。因此推荐使用P字命名法。

baksmail默认使用 p 命名法,如果想要使用v 命名法,加 -p/-no-parameter-register寄存器

5.Long/Double 值

Long/Double基本类型是64bit值,因此需要两个寄存器存放 它们的值。

假设你有一个非静态方法LMyObject;->MyMethod(IIJ)V,方法MyMethod,该方法需要5个寄存器来保存参数,如下

p0this
p1I
p2,p3J
p4Z
本文参考自:

[1] https://github.com/JesusFreke/smali/wiki/TypesMethodsAndFields

[2]https://github.com/JesusFreke/smali/wiki/Registers
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: