阅读 217

一文带你深入android的smali的指令解析

1.普通字段读写操作

iget-object vAA,vBB,filed_id: 表示读取vAA寄存器中的对象中的filed_id对象的引用值给VBB寄存器。
iget_boolean vAA,vBB,filed_id: 表示读取vAA寄存器中的对象中的filed_id的值给vBB寄存器。
iget_wide vAA,vBB,filed_id :表示读取vAA寄存器中对象中的filed_id的值给vBB寄存器。 iget vAA,vBB,filed_id:表示vAA寄存器中对象的filed_id值给vBB寄存器。

iput-object vAA,vBB,filed_id:表示把vAA寄存器指向的对象的引用赋值给vBB寄存器中的filed_id。 iput-boolean vAA,vBB,filed_id:表示把vAA寄存器的值给vBB寄存器中的boolean类型。
iput_wide vAA,vBB,filed_id:表示把vAA寄存器的值给vBB寄存器的wide类型。
iput vAA,vBB,filed_id: 表示把vAA寄存器的值给vBB寄存器的int类型。

aget vx,vy,vz 表示从int数组获取一个int型的值到vx,对象数组的引用位于vy,需获取的元素的索引位于vz。
age-wide vx,vy,vz 表示从long/double数组获取一个long/double值到vx,vx+1,数组的引用位于vy,需获取元素的索引位于vz。

2.静态字段的读写操作

sget-object vAA,vBB,filed_id: 表示读取vAA寄存器中的对象中的filed_id对象的引用值给VBB寄存器。
sget_boolean vAA,vBB,filed_id: 表示读取vAA寄存器中的对象中的filed_id的值给vBB寄存器。
sget_wide vAA,vBB,filed_id :表示读取vAA寄存器中对象中的filed_id的值给vBB寄存器。 sget vAA,vBB,filed_id:表示vAA寄存器中对象的filed_id值给vBB寄存器。

sput-object vAA,vBB,filed_id:表示把vAA寄存器指向的对象的引用赋值给vBB寄存器中的filed_id。
sput-boolean vAA,vBB,filed_id:表示把vAA寄存器的值给vBB寄存器中的boolean类型。
sput_wide vAA,vBB,filed_id:表示把vAA寄存器的值给vBB寄存器的wide类型。
sput vAA,vBB,filed_id: 表示把vAA寄存器的值给vBB寄存器的int类型。

3.跳转指令

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-switch vAA, +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-testz vAA, +BBBB:条件跳转指令。拿vAA寄存器与0比较,如果比较结果满足或值为0时就跳转到BBBB指定的偏移处。偏移量BBBB不能为0。 if-testz类型的指令有以下几条:

if-eqz:如果vAA为0则跳转。Java语法表示为“if(vAA == 0)”

if-nez:如果vAA不为0则跳转。Java语法表示为“if(vAA != 0)”

if-ltz:如果vAA小于0则跳转。Java语法表示为“if(vAA < 0)”

if-gez:如果vAA大于等于0则跳转。Java语法表示为“if(vAA >= 0)”

if-gtz:如果vAA大于0则跳转。Java语法表示为“if(vAA > 0)”

if-lez:如果vAA小于等于0则跳转。Java语法表示为“if(vAA <= 0)”

4.比较指令

它的格式: cmpkind vAA, vBB, vCC :其中vBB寄存器与vCC寄存器是需要比较两个寄存器,比较结果放到vAA寄存器中。

Dalvik指令集共有5个比较指令 cmpl-float vAA, vBB, vCC: 比较两个单精度浮点数,如果vBB寄存器大于vCC寄存器,结果为-1,相等则结果为0,小于的话结果为1。
cmpg-float vAA, vBB,vCC :比较两个单精度浮点数,如果vBB寄存器大于VCC寄存器,结果为1,相等结果为0,小于的话结果为-1。
cmpl-double vAA, vBB,vCC: 比较两个双精度浮点数,如果VBB寄存器大于VCC寄存器,结果为-1,相等结果为0,小于的话为1。
cmpg-double vAA, vBB,vCC: 比较两个双精度浮点数,如果VBB寄存器大于VCC寄存器,结果为1,相等结果为0,小于的话为-1。
cmp-long vAA, vBB, vCC:比较两个长整型,如果vBB寄存器大于vCC寄存器,结果为1,相等结果为0,小于结果为-1。

5.数据转换指令

它的格式: unop vA,vB:vB寄存器转换到对应数据并将结果放到vA寄存器上。

.“neg-int”:对整型数求补。

.“not-int”:对整型数求反。

.“neg-long”:对长整型数求补。

.“not-long”:对长整型数求反

.“neg-float”:对单精度浮点型数求补。

.“neg-double”:对双精度浮点型数求补。

.“int-to-long”:将整型数转换为长整型。

.“int-to-float”:将整型数转换为单精度浮点型数。

.“int-to-dobule”:将整型数转换为双精度浮点数。

.“long-to-int”:将长整型数转换为整型。

.“long-to-float”:将长整型数转换为单精度浮点型。

.“long-to-double”:将长整型数转换为双精度浮点型。

.“float-to-int”:将单精度浮点数转换为整型。

.“float-to-long”:将单精度浮点数转换为长整型数。

.“float-to-double”:将单精度浮点数转换为双精度浮点型数。

.“double-to-int”:将双精度浮点数转换为整型。

.“double-to-long”:将双精度浮点数转换为长整型。

.“double-to-float”:将双精度浮点数转换为单精度浮点型。

.“int-to-byte”:将整型转换为字节型。

.“int-to-char”:将整型转换为字符型。

.“int-to-short”:将整型转换为短整型。

6.数据运行指令

数据运算指令包括算术运算指令与逻辑运算指令。
算术运算指令主要进行数值间如加,减,乘,除,模,移位等运算。
逻辑运算指令主要进行数值间与,或,非,抑或等运算。
数据运算指令有如下四类(数据运算时可能是在寄存器或寄存器对间进行,下面的指令作用讲解时使用寄存器来描述):

.“binop vAA, vBB, vCC”:将vBB寄存器与vCC寄存器进行运算,结果保存到vAA寄存器。

.“binop/2addr vA, vB”:将vA寄存器与vB寄存器进行运算,结果保存到vA寄存器。

.“binop/lit16 vA, vB, #+CCCC”:将vB寄存器与常量 CCCC进行运算,结果保存到vA寄存器。

.“binop/lit8 vAA, vBB, #+CC”:将vBB寄存器与常量CC进行运算,结果保存到vAA寄存器。

后面3类指令比第1类指令分别多出了2addr,lit16,lit8等指令后缀。四类指令中基础字节码相同的指令执行的运算操作是类似的,第1类指令中,根据数据的类型不同会在基础字节码后面加上数据类型后缀,如 -int 或 -long 分别表示操作的数据类型为整型与长整型。

第1类指令可归类如下:

.“add-type”:vBB寄存器与vCC寄存器值进行加法运算(vBB + vCC)

.”sub-type”:vBB寄存器与vCC寄存器值进行减法运算(vBB - vCC)

.”mul-type”:vBB寄存器与vCC寄存器值进行乘法运算(vBB * vCC)

.”div-type”:vBB寄存器与vCC寄存器值进行除法运算(vBB / vCC)

.”rem-type”:vBB寄存器与vCC寄存器值进行模运算(vBB % vCC)

.”and-type”:vBB寄存器与vCC寄存器值进行与运算(vBB & vCC)

.”or-type”:vBB寄存器与vCC寄存器值进行或运算(vBB | vCC)

.”xor-type”:vBB寄存器与vCC寄存器值进行异或运算(vBB ^ vCC)

.”shl-type”:vBB寄存器值(有符号数)左移vCC位(vBB << vCC )

.”shr-type”:vBB寄存器值(有符号)右移vCC位(vBB >> vCC)

.”ushr-type”:vBB寄存器值(无符号数)右移vCC位(vBB >>> vCC)

7.方法调用指令

.invoke-virtual或 invoke-virtual/range调用实例的虚方法。 .invoke-super或”invoke-super/range调用实例的父类方法。 .invoke-direct或“invoke-direct/range调用实例的直接方法。 .invoke-static或invoke-static/range调用实例的静态方法。 .invoke-interface或invoke-interface/range调用实例的接口方法

8.异常处理指令

.throw vAA:抛出vAA寄存器中指定类型的异常。

9.返回指令

.return-void: 表示函数从一个void返回 .return vAA: 表示函数返回一个32位非对象类型的值,返回值寄存器为8位的寄存器vAA .return-wide vAA: 表示函数返回一个64位飞对象类型的值,反黑值为8位的寄存器对vAA .return-object vAA:表示函数返回一个对象类型的值,返回值为8位寄存器vAA。

10.数据操作指令

.move vA, vB:将vB寄存器的值赋给vA寄存器,A源寄存器与目的寄存器都为4位。
.move/from16 vAA, vBBBB:将vBBBB寄存器的值赋给vAA寄存器,源寄存器为16位,目的寄存器为8位。
.move/16 vAAAA, vBBBB:将vBBBB寄存器的值赋给vAAAA寄存器,源寄存器与目的寄存器都为16位。

.move-wide vA, vB:为4位的寄存器对赋值。源寄存器与目的寄存器都为4位。
.move-wide/from16 vAA, vBBBB 与“move-wide/16 vAAAA, vBBBB”实现与“move-wide”相同。
.move-object vA, vB:为对象赋值。源寄存器与目的寄存器都为4位。
.move-object/from16 vAA, vBBBB:为对象赋值。源寄存器为16位,目的寄存器为8位。
.move-object/16 vAA, vBBBB:为对象赋值。源寄存器与目的寄存器都为16位。

.move-result vAA:将上一个invoke类型指令操作的单字非对象结果赋给vAA寄存器。

.move-result-wide vAA:将上一个invoke类型指令操作的双字非对象结果赋给vAA寄存器。

.move-result-object vAA:将上一个invoke类型指令操作的对象结果赋给vAA寄存器。

.move-exception vAA:保存一个运行时发生的异常到vAA寄存器,这条指令必须是异常发生时的异常处理器的一条指令。否则的话,指令无效。

.registers指令指定了在这个方法中有多少个可用寄存器。
.locals指明了在这个方法中非参寄存器的数量。

文章分类
Android
文章标签