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 }