第3章 Android Dalvik指令
1、 环境配置 Ubuntu 15.10 IP:192.168.153.130
2、 Dalvik指令使用
1、 实例操作指令
Check-case vAA ,type@BBBB 将vAA寄存器中对象引用转换成指定类型,会抛出异常。
因为如果B指定是基本类型,对于非基本类型的A来说会始终失败。
Instance-of vA ,vB ,type@CCCC 判断vB寄存器中的对象引用是否可以转换成指定的类型,如果vA寄存器值为1
New-instance vAA ,type@BBBB 构造一个指定的新实例,并将引用赋值给vAA寄存器,tpye指定的类型不能为数组类。
Check-case/jumbo vAAAA ,type@BBBBBBBB 指令功能跟Check-case vAA ,type@BBBB一样,只是寄存器的值和索引取值范围更大。
Instance-of vAAAA ,vBBBB ,type@CCCCCCCC 指令功能跟Instance-of vA ,vB ,type@CCCC一样,只是寄存器的值和索引取值范围更大。
New- Instance/jumbo vAAAA ,type@BBBBBBBB指令功能与New-instance vAA ,type@BBBB一样,只是寄存器的值和索引取值范围更大。
2、 数组操作指令
Array-length vA ,vB 获取给定vB寄存器中数组的长度并将值赋给vA 寄存器,数组长度指的是数组的条目个数。
New-array vA ,vB,type@CCCC 构造指定类型(type@CCCC)与大小(vB)的数组,并将值赋给vA寄存器。
Filed-new-array{vC ,vD ,vE ,vF ,vG},type@BBBB构造指定类型(type@BBBB)与大小(vA)的数组并填充数组内容。vA 寄存器是隐含使用的,除了指定数组的大小外还指定了参数的个数,vC~vG是使用到的参数寄存器序列。
Filled-new-array/range{vCCCC…vNNNN},type@BBBB 指令功能与filed-new-array{vC ,vD
,vE ,vF ,vG },type@BBBB 相同,只是参数寄存器使用range字节码后缀指定了取值范围,vC是第一个参数寄存器,N=A+C -1.
Fill-array-data vAA ,+BBBBBBBB用指定的数据来填充数组,vAA寄存器为数组引用,引用必须为基础类型的数组,在指令后面会紧跟一个数据表。
New-array/jumbo vAAAA ,vBBBB ,type@CCCCCCCC指令功能与New-array vA ,vB,type@CCCC相同,只是寄存器值与指令的索引取值范围更大。
Filled-new-array/jumbo{vCCCC …vNNNN},type@BBBBBBBB指令功能与Filled-new-array/range{vCCCC…vNNNN},type@BBBB相同,只是索引取值范围更大。
Arrayop vAA ,vBB ,vCC 对vBB寄存器指定的数组元素进入取值与赋值。vCC寄存器指定数组元素索引,vAA 寄存器用来存放读取的或需要设置的数组元素的值。读取元素使用aget类指令,元素赋值使用aput类指令。数组中存储的类型指令后面会紧跟不同的指令后缀,指令分为: aget、aget-wide、aget-object、aget-boolean、aget-byte、aget-char、
Aget-short、aput、aput-wide、aput-object、aput-boolean、aput-byte、aput-char、aput-short。
3、 异常指令
Throw vAA 抛出vAA 寄存器中指定类型的异常。
4、跳转指令
Dalvik指令集中有三种跳转指令:
无条件跳转(goto)、分支跳转(switch)、条件跳转(if).
Goto+AA 无条件跳转到指定偏移处,偏移量AA不能为0.
Goto/16+AAAA 无条件跳转到指定偏移处,偏移量AAAA不能为0.
Goto/32+AAAAAAAA 无条件跳转到指定偏移处。
Packed-switch vAA,+BBBBBBBB 分支跳转指令。vAA ,寄存器为switch分支中需要判断的值,BBBBBBBB指向一个packed-switch-payload格式的偏移表,表中的值是有规律递增的。
Sparse-switchvAA ,+BBBBBBBB分支跳转指令。vAA寄存器为switch分支中需要判断的值,BBBBBBBB指向一个sparse-switch-payload格式的偏移表,表中的值是无规律的偏移量。
If-test vA,vB,+CCCC条件跳转指令。vA寄存器与vB寄存器的值,如果比较结果满足就跳转到CCCC指定的偏移处。偏移量CCCC不能为0,if-test类型的指令有以下几种:
If-eq 如果vA 等于 vB 则跳转。Java语法表示为if(vA==vB)
If-ne 如果vA 不等于vB则跳转。Java语法表示为if(vA!=vB)
If-lt 如果vA 小于vB则跳转。Java语法表示为 if(vA < vB)
If-ge 如果vA 大于等于vB则跳转。Java语法表示if(vA >=vB)
If-gt 如果vA 大于vB则跳转。Java语法表示为 if(vA > vB)
If-le 如果vA 小于等于vB则跳转。Java语法表示为if(vA <=vB)
If-testzvAA,+BBBB条件跳转指令。拿vAA寄存器与0比较,如果比较结果满足或值为0时就跳转到BBBB指定的偏移处。偏移量BBBB不能为0. If-testz 类型指令有以下几条:
If-eq 如果vAA为0则跳转。Java语法表示为 if(!vAA)
If-nz 如果vAA 不为0则跳转。Java语法表示为if(vAA)
If-lt 如果vAA小于0则跳转。Java语法表示为if(vAA <0)
If-ge 如果vAA 大于等于0则跳转。Java语法表示为if(vAA >=0)
If-gt 如果vAA大于0则跳转。Java语法表示为if(vAA > 0)
If-le 如果vAA 小于等于0则跳转。Java语法表示为if(vAA <=0)
5、比较指令
Cmpl-float 比较两个单精度浮点数。如果vBB寄存器大于vCC寄存器,则结果为-1,相等则结果为0,小于的话结果为1.
Cmpg-float 比较两个单精度浮点数。如果vBB寄存器对大于vCC寄存器对,则结果为1,相等则结果为0,小于的话结果为-1.
Cmpl-double 比较两个双精度浮点数。如果vBB寄存器对大于vCC寄存器对,则结果-1,相等则结果为0小于的话结果为1.
Cmpg-double 比较两个双精度浮点数。如果vBB寄存器对大于vCC寄存器对,则结果为1,相等则结果为0,小于的话结果为-1.
Cmp-long 比较两个长整型数。如果vBB寄存器大于vCC寄存器,则结果为1,相等则结果为0,小于的话结果为-1.
6、字段操作指令
字段分为普通和静态两种,普通字段以i打头,静态字段以s打头。
分别为:iinstanceop vA,vB,field@CCCC 和sstanceop vA,vB,field@CCCC
7、方法调用指令
方法调用指令负责调用类实例的方法。它的基础指令为invoke,方法调用指令有
Invoke-kind{vC,vD,vE,vF ,vG},meth@BBBB
与invoke-kind/range{vCCCC …vNNNN},meth@BBBB两类,两类指令在作用上并无不同,只是后者在设置参数寄存器时使用了range来指定寄存器的范围。根据方法类型的不同,共有5条方法调用指令。
Invoke-virtual 或invoke-virtual/range 调用实例的虚方法。
Invoke-super 或invoke-super/range 调用实例的父类方法。
Invoke-direct 或invoke-direct/range 调用实例的直接方法。
Invoke-static 或 invoke-static/rangs调用实例的静态方法。
Invoke-interface 或invoke-interface/range 调用实例的接口方法。
8、数据转换指令
Neg-int对整型数求补
Not-int对整型数求反
Int-to-long将整型数转换长整型
int-to-float将整型数转换为单精度浮点数
int-to-double将整型数转换为双精度浮点型
long-to-int将长整型转换为整型
long-to-float将长整型数装潢为单精度浮点数
long-to-double将长整型数转换为双精度浮点数
注意:记住类型转类型中间都有一个“to”
9、数据运算指令
BinopvAA,vBB ,vCC 将vBB寄存器与vCC寄存器进行运算,结果保存到vAA寄存器。
Binop/2addrvA ,vB 将vA寄存器与vB寄存器进行运算,结果保存到vA寄存器。
Binop/lit16vA ,vB,#+CCCC将vB寄存器与常量CCCC进行运算,结果保存到vA寄存器。
Binop/lit8vAA ,Vbb,#+CC 将vBB寄存器与常量CC进行运算,结果保存到vAA寄存器。
后面3类指令比第1类指令分别多出了2addr、lit16、lit8等指令后缀。四类指令中基础字节码相同的指令执行的运算操作是类似的,第1类指令中,根据数据的类型不同会在 基础字节码后面加上数据类型后缀,如-int或-long分别表示操作的数据类型为整型与长整型。第1类指令可归类如下:
Add-typevBB寄存器与vCC寄存器值进行加法运算 (vBB+vCC).
Sub-typevBB寄存器与vCC寄存器值进行减法运算(vBB -vCC).
Mul-typevBB寄存器与vCC寄存器值进行乘法运算(vBB * vCC ).
div-type vBB寄存器与vCC寄存器值进行除法运算(vBB /vCC ).
Rem-typevBB寄存器与vCC寄存器值进行模运算(vBB % vCC).
And-typevBB 寄存器与vCC寄存器值进行与运算(vBB and vCC).
Or-typevBB寄存器与vCC寄存器值进行或运算(vBB or vCC ).
Xor-typevBB 寄存器vCC寄存器值进行异运算(vBB xor vCC ).
Shl-typevBB寄存器值(有符号数) 左移vCC位(vBB << vCC).
Shr-typevBB寄存器值(有符号数) 右移vCC位(vBB >> vCC).
Ushr-typevBB寄存器值(无符号数)右移vCC位(vBB >>vCC).