1、Dalvik虚拟机介绍
Dalvik虚拟机基于寄存器架构,在代码中大量地使用了寄存器。Dalvik将部分寄存器映射到了ARM寄存器上面,还有部分通过调用栈进行模拟。Dalvik中用到的寄存器都是32位的,如果是表示64位的寄存器,则使用相邻的两个寄存器一起表示。
在Dalvik中,寄存器采用v0作为起始值,最大可以取值到v65535。每个函数都在函数头部使用.registers指定函数需要用到的寄存器数目,当虚拟机执行到这个函数时,会根据寄存器的数目分配适当的栈控件,这些控件就是用来存放寄存器实际的值的!在Android SDK中有一个名为dalvik.bytecode.Opcodes的接口。
2、寄存器命名规则
v命名法采用小写的“v”开头,表示函数中用到的局部变量与参数,所有的寄存器命名从v0开始,依次递增。
p命名法采用小写的“p”开头,其命名规则是:函数中引入的参数命名从p0开始,依次递增。
假设一个函数中使用到了M个寄存器,并且该函数有N个参数,根据Dalvik虚拟机参数传递方式中的规定:参数使用最后的N个寄存器中,局部变量使用从v0开始的前M-N个寄存器。下面给出一副图示说明:
比较:使用P命名是为了防止以后如果在方法中增加寄存器,需要对参数寄存器重新进行编号的缺点
特别说明一下:Long和Double类型是64位的,需要2个寄存器
3、JAVA代码示例
public class Hello{
public int fun(int a,int b){
return (a+b)*(a-b);
}
public static void main(String[] args){
Hello hello = new Hello();
System.out.println(hello.fun(5,3));
}
}
操作步骤:
命令提示符,生成class文件,命令为:javac Hello.java
然后执行生成dex文件的命令:dx --dex --output=Hello.dex Hello.class
注意,直接敲入该命令,可能出现错误,应该找到dx命令的路径,仅以笔者的路径为例子:D:\android4.4\sdk\build-tools\android-4.4W
会在对应目录产生一个Hello.dex的文件
然后执行javap -c -classpath . Hello
得到JAVA字节码:
public class Hello extends java.lang.Object{
public Hello();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public int fun(int, int);
Code:
0: iload_1
1: iload_2
2: iadd
3: iload_1
4: iload_2
5: isub
6: imul
7: ireturn
public static void main(java.lang.String[]);
Code:
0: new #2; //class Hello
3: dup
4: invokespecial #3; //Method "<init>":()V
7: astore_1
8: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_1
12: iconst_5
13: iconst_3
14: invokevirtual #5; //Method fun:(II)I
17: invokevirtual #6; //Method java/io/PrintStream.println:(I)V
20: return
}