目录
DVM有专用的指令集和专门的指令格式DEX。
其一些特点如下:
1、基于寄存器的设计。方法在内存创建后有固定大小的栈帧。
2、如果整数与浮点数按位表示,可以用32位寄存器来存放。
3、指令流以16位无符号整型为存储单元。
2.1Dalvik指令格式
例如,“B|A|op CCCC
”格式表示其包含两个 16 位代码单元。第一个指令字的高八位是 2 个四位值,低八位是指令码;第二个指令字是一个 16 位值。
例:A|G|op BBBB F|E|D|C
每16位用空格隔开;
每个字母表示4位,中间可以用“|”隔开;
在大部分情况下,字母按照代码单元的顺序进行排列,代码单元中按照从低位到高位的顺序进行排序;
顺序采用大写A~Z字母表示4位值,op表示8位操作码;
1、格式ID:
用来确定指定指令格式的编码。是格式表中的第二列表示格式的短标识符,用于在其他文档和代码中识别该格式。
大多数格式 ID 包含三个字符:例:21t
前两个是十进制数,最后一个是字母。
第一个十进制数表示格式中 16 位代码单元的数量。
第二个数字表示格式所含寄存器的数量上限(因为某些格式使用的寄存器数量是可变的),特殊标识“r
”表示编码了一系列寄存器。
最后一个字母以半助记符的形式表示该格式编码的任何其他数据类型。
例如,“21t
”格式的长度为 2,包含一个寄存器引用,另外还包含一个分支目标。
助记符 | 位数 | 含义 |
---|---|---|
b | 8 | 有符号立即数(字节) |
c | 16、32 | 常量池索引 |
f | 16 | 接口常量(仅对静态链接格式有效) |
h | 16 | 有符号立即数 hat(32 位或 64 位值的高阶位,低阶位全为 0 ) |
i | 32 | 有符号立即数(整型)或 32 位浮点数 |
l | 64 | 有符号立即数(长整型)或 64 位双精度浮点数 |
m | 16 | 方法常量(仅对静态链接格式有效) |
n | 4 | 有符号立即数(半字节) |
s | 16 | 有符号立即数(短整型) |
t | 8、16、32 | 分支目标 |
x | 0 | 无额外数据 |
2、Dalvik指令语法:
每条指令都是从操作码开始,后面紧跟参数,个数不定,用逗号“,”分隔。
参数为“vX”,说明是一个寄存器。
参数为“#+X”,说明是一个常量数字;
参数为“+X”,是相对指令的地址偏移量;
如果为“kind@X”格式,是常量池索引值。如果kind为string(字符串常量池索引),type(类型),field(字段),meth(方法)。
例:op vAA, string@BBBB
该指令使用了一个寄存器参数vAA,附加了一个字符串常量池索引值string@BBBB。
2.2Dalvik寄存器:
Dalvik使用的寄存器全部为32位。
一个指令: op vAAAA,vBBBB
其中每个大写字母代表四位,故AAAA,BBBB的最大值为,即65535。寄存器初始值为0,范围为v0~v65535。
寄存器命名法:
源代码详细信息:http://t.csdn.cn/KAMH2
下面为v命名法
Virtual methods -
#0 : (in LHello;)
name : 'foo'
type : '(II)I'
access : 0x0001 (PUBLIC)
code -
registers : 5
ins : 3
outs : 0
insns size : 6 16-bit code units
000198: |[000198] Hello.foo:(II)I
0001a8: 9000 0304 |0000: add-int v0, v3, v4
0001ac: 9101 0304 |0002: sub-int v1, v3, v4
0001b0: b210 |0004: mul-int/2addr v0, v1
0001b2: 0f00 |0005: return v0
catches : (none)
positions :
0x0000 line=4
locals :
0x0000 - 0x0006 reg=2 this LHello;
source_file_idx : 1 (Hello.java)
假设一个函数需使用M个寄存器,且该函数一共有N个参数。那么参数使用最后N个寄存器,局部变量使用前面M-N个寄存器。
例如上面的代码:由于foo()函数是非静态方法,被调用时会传入一个隐式的Hello对象引用,因此实际上传入了三个参数。
故v2,v3,v4这三个寄存器由参数使用。v2用于表示被传入的Hello对象的引用。v3,v4用于传入的两个整形参数。
v0,v1用于表示函数的局部变量寄存器。
p命名法就是将前面的v2,v3,v4换成p0,p1,p2。其余基本一致。
2.3Dalvik字节码:
1、类型
Dalvik字节码只有基本类型和引用类型。除了对象和数组属于引用对象,其余Java类型全为引用类型。
java类型 | 类型描述符 |
---|---|
boolean | Z |
byte | B |
short | S |
char | C |
int | I |
long | J |
float | F |
double | D |
void,只用于返回值类型 | v |
java类类型 | L |
数组类型 | [ |
每个Dalvik寄存器都为32位,对J,D等64位的类型是用两个相邻的寄存器来存储。
例:
Lpackage/name/ObjectName;
L表示后面是一个java类,package/name/表示类所在的包,ObjectName表示对象的名称,分号表示对象名结束。
对应的java代码:
package.name.ObjectName
2、方法
Lpackage/name/ObjectName;->MethodName(III)Z
类型(Lpackage/name/ObjectName;)、具体方法名(MethodName)、方法签名部分((III)Z)。其中三个III表示为三个int类型的参数;Z表示返回类型为boolean。
更复杂的例子:
method(I[[IIjava/lang/String;[Ljava/langObject;)Ljava/lang/String;
对应的Java代码:
String method(int, int[][], int, String, Object[])
baksmali生成的方法代码以 .method 开始,以 .endmethod 结束。
#后面的为注释;# virtual methods 虚方法 ; #direct methods 直接方法
3、字段
与方法类似,不过没有参数和返回值。
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;
字段由类型(Lpackage/name/ObjectName;)、字段名(FeildName)、字段类型(Ljava/lang/String;)组成。其中名和类型中间用冒号“:”分隔。
baksmali生成的字段代码以 .field指令开头。
# instance fields 实例字段 ; # static fields 静态字段
参考书目:《Android软件安全权威指南》《Android进阶解密》