[转载]dalvik smali 语法
原文地址:dalvik smali 语法作者: harrison dalvik字节码有两种类型,原始类型和引用类型。对象和数组是引用类型,其它都是原始类型。 v void,只能用于返回值类型z booleanb bytes shortc chari intj long(64位)f floatd do ble(64位) 1. 对象 对象以lpackagenameobjectname；的形式表示。 前面的l表示这是一个对象类型,packagename是该对象所在的包,objectname是对象的名字,"；"表示对 象名称的结束。相当于java中的package.name.objectname。例如:ljavalangstring；相java.lang.string 2.数组 数组的表示形式 [i-表示一个整型一维数组,相当于java中的int[]。 对于多维数组,只要增加[就行了。[[i相当于int[][],i相当于int[][][]。注意每一维的最多255个。 对象数组的表示:[ljavalangstring；表示一个string对象数组。 3.方法 表示形式:lpackagenameobjectname；-methodname(iii)z lpackagenameobjectname；表示类型,methodname是方法名。iii为参数(在此是3个整型参数),z是返回 类型(bool型)。 方法的参数是一个接一个的,中间没有隔开。 一个更复杂的例子: method(i[[iiljavalangstring；[ljavalangobject；)ljavalangstring； 在java中则为:string method(int, int[][], int, string, object[]) 4.字段 表示形式:lpackagenameobjectname；-fieldname:ljavalangstring； 即包名,字段名和各字段类型。 5.寄存器 在dalvik字节码中,寄存器都是32位的,能够支持任何类型。64位类型(long和do ble型)用2个寄存器表 示。 有两种方式指定一个方法中有多少寄存器是可用的。.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中。 对于静态方法除了没有隐含的this参数外其它都一样。 6.寄存器的命名方式 有两种方式-v命名方式和p命名方式。p命名方式中的第一个寄存器就是方法中的第一个参数寄存器。在下 表中我们用这两种命名方式来表示上一个例子中有5个寄存器和3个参数的方法。 v0 第一个local register v1 第二个local register v2 p0 第一个parameter register v3 p1 第二个parameter register v4 p2 第三个parameter register 你可以用任何一种方式来引用参数寄存器-他们没有任何差别。 注意:baksmali默认对参数寄存器使用p命名方式。如果想使用v命名方式,可以使用-pl-no-parameter- registers选项。 使用p命名方式是为了防止以后如果要在方法中增加寄存器,需要对参数寄存器重新进行编号的缺点。 longdo ble值 long和do ble类型是64位的,需要2个寄存器(切记切记)。 例如,对于非静态方法lmyobject；-mymethod(ijz)v,参数分别是lmyobject；,int,long,bool。故该方法 需要5个寄存器来存储参数。 p0 this p1 i p2,p3 j p4 z other: # static fields 定义静态变量的标记 # instance fields 定义实例变量的标记 # direct methods 定义静态方法的标记 # virt al methods 定义非静态方法的标记 构造函数的返回类型为v,名字为init。 if-eq p1, v0, :cond_8 表示如果p1和v0相等,则执行cond_8的流程: :cond_8 invoke-direct {p0}, lcompa ltesta；-dv 调用com.pa l.test.a的d方法 if-ne p1, v0, :cond_b 表示不相等则执行cond_b的流程: :cond_b const4 v0, 0x0 invoke-virt al {p0, v0}, lcompa ltesta；-setpressed(z)v invoke-s per {p0, p1, p2}, landroidviewview；-onkeyup(ilandroidviewkeyevent；)z move-res lt v0 大概意思就是调用com.pa l.test.a的setpressed方法,然后再调用父类view的onkeyup方法,最后 ret rn v0 举两个例子: 01. sget-object v5, lcomgoogleyo ngandroidr ntime；-lit227:lgn mappingsimplesymbol； 获取com.google.yo ngandroid.r ntime中的lit227字段存入v5寄存器,相当于 gn .mapping.simplesymbol localvariable = com.google.yo ngandroid.r ntime.lit227； 02. sp t-object v0, lcomgoogleyo ngandroidr ntime；-lit78:lkawalangsyntaxtemplate； likewise, this is setting the val e of a static field. i.e. 设置com.google.yo ngandroid.r ntime.lit78的值为v0寄存器中的kawa.lang.syntaxtemplate类型变量的 值。相当于com.google.yo ngandroid.r ntime.lit78 = kawa.lang.syntaxtemplate localvariable； 03. const 4 vx, lit4 表示存入4位常量到vx寄存器 inp t-object vx, vy, 字段id 根据 字段id将vx寄存器的值存入实例的对象引用字段,vy寄存器中是 该实例的引用。 那么什么叫对象的引用呢？ class a{类体内容 } a a1 它代表a是类,a1是引用,a1不是对象,a1所指向的对象为空n ll； 这样就好理解下面的例子: const4 v0, 0x0 ip t-object v0, p0, lcomexampleb ttonmainactivity；-btn1:landroidwidgetb tton； p0 --this (b tton) 相当于android.widget.b tton btn1 = v0；