Dalvik虚拟机操作码作者:GaborPaller翻译:YULIANGMAXv1.0表中的vx、vy、vz表示某个Dalvik寄存器。根据不同指令可以访问16、256或64K寄存器。表中lit4、lit8、lit16、lit32、lit64表示字面值(直接赋值),数字是值所占用位的长度。long和double型的值占用两个寄存器,例:一个在v0寄存器的double值实际占用v0,v1两个寄存器。boolean值的存储实际是1和0,1为真、0为假;boolean型的值实际是转成int型的值进行操作。所有例子的字节序都采用高位存储格式,例:0F000A00的编译为0F,00,0A,00存储。有一些指令没有说明和例子,因为我没有在正常使用中看到过这些指令,它们的存在是从这里知道的:Androidopcodeconstantlist。Opcode操作码(hex)Opcodename操作码名称Explanation说明Example示例00nop无操作0000-nop01movevx,vy移动vy的内容到vx。两个寄存器都必须在最初的256寄存器范围以内。0110-movev0,v1移动v1寄存器中的内容到v0。02move/from16vx,vy移动vy的内容到vx。vy可能在64K寄存器范围以内,而vx则是在最初的256寄存器范围以内。02001900-move/from16v0,v25移动v25寄存器中的内容到v0。03move/16未知注404move-wide未知注405move-wide/from16vx,vy移动一个long/double值,从vy到vx。vy可能在64K寄存器范围以内,而vx则是在最初的256寄存器范围以内。05160000-move-wide/from16v22,v0移动v0,v1寄存器中的内容到v22,v23。06move-wide/16未知注407move-objectvx,vy移动对象引用,从vy到vx。0781-move-objectv1,v8移动v8寄存器中的对象引用到v1。08move-object/from16vx,vy移动对象引用,从vy到vx。vy可以处理64K寄存器地址,vx可以处理256寄存器地址。08011500-move-object/from16v1,v21移动v21寄存器中的对象引用到v1。09move-object/16未知注40Amove-resultvx移动上一次方法调用的返回值到vx。0A00-move-resultv0移动上一次方法调用的返回值到v0。0Bmove-result-widevx移动上一次方法调用的long/double型返回值到vx,vx+1。0B02-move-result-widev2移动上一次方法调用的long/double型返回值到v2,v3。0Cmove-result-objectvx移动上一次方法调用的对象引用返回值到vx。0C00-move-result-objectv0移动上一次方法调用的对象引用返回值到v0。0Dmove-exceptionvx当方法调用抛出异常时移动异常对象引用到vx。0D19-move-exceptionv25当方法调用抛出异常时移动异常对象引用到v25。0Ereturn-void返回空值。0E00-return-void返回值为void,即无返回值,并非返回null。0Freturnvx返回在vx寄存器的值。0F00-returnv0返回v0寄存器中的值。10return-widevx返回在vx,vx+1寄存器的double/long值。1000-return-widev0返回v0,v1寄存器中的double/long值。11return-objectvx返回在vx寄存器的对象引用。1100-return-objectv0返回v0寄存器中的对象引用。12const/4vx,lit4存入4位常量到vx。1221-const/4v1,#int2存入int型常量2到v1。目的寄存器在第二个字节的低4位,常量2在更高的4位。13const/16vx,lit16存入16位常量到vx。13000A00-const/16v0,#int10存入int型常量10到v0。14constvx,lit32存入int型常量到vx。14004E61BC00-constv0,#12345678//#00BC614E存入常量12345678到v0。15const/high16v0,lit16存入16位常量到最高位寄存器,用于初始化float值。15002041-const/high16v0,#float10.0//#41200000存入float常量10.0到v0。该指令最高支持16位浮点数。16const-wide/16vx,lit16存入int常量到vx,vx+1寄存器,扩展int型常量为long常量。16000A00-const-wide/16v0,#long10存入long常量10到v0,v1寄存器。17const-wide/32vx,lit32存入32位常量到vx,vx+1寄存器,扩展int型常量到long常量。17024e61bc00-const-wide/32v2,#long12345678//#00bc614e存入long常量12345678到v2,v3寄存器。18const-widevx,lit64存入64位常量到vx,vx+1寄存器。1802874b6b5d54dc2b00-const-widev2,#long12345678901234567//#002bdc545d6b4b87存入long常量12345678901234567到v2,v3寄存器。19const-wide/high16vx,lit16存入16位常量到最高16位的vx,vx+1寄存器,用于初始化double值。19002440-const-wide/high16v0,#double10.0//#402400000存入double常量10.0到v0,v1。1Aconst-stringvx,字符串ID存入字符串常量引用到vx,通过字符串ID或字符串。1A080000-const-stringv8,//string@0000存入string@0000(字符串表#0条目)的引用到v8。1Bconst-string-jumbo未知注41Cconst-classvx,类型ID存入类对象常量到vx,通过类型ID或类型(如Object.class)。1C000100-const-classv0,Test3//type@0001存入Test3.class(类型ID表#1条目)的引用到v0。1Dmonitor-entervx获得vx寄存器中的对象引用的监视器。1D03-monitor-enterv3获得v3寄存器中的对象引用的监视器。1Emonitor-exit释放vx寄存器中的对象引用的监视器。1E03-monitor-exitv3释放v3寄存器中的对象引用的监视器。1Fcheck-castvx,类型ID检查vx寄存器中的对象引用是否可以转换成类型ID对应类型的实例。如不可转换,抛出ClassCastException异常,否则继续执行。1F040100-check-castv4,Test3//type@0001检查v4寄存器中的对象引用是否可以转换成Test3(类型ID表#1条目)的实例。20instance-ofvx,vy,类型ID检查vy寄存器中的对象引用是否是类型ID对应类型的实例,如果是,vx存入非0值,否则vx存入0。20400100-instance-ofv0,v4,Test3//type@0001检查v4寄存器中的对象引用是否是Test3(类型ID表#1条目)的实例。如果是,v0存入非0值,否则v0存入0。21array-lengthvx,vy计算vy寄存器中数组引用的元素长度并将长度存入vx。2111-array-lengthv0,v1计算v1寄存器中数组引用的元素长度并将长度存入v0。22new-instancevx,类型ID根据类型ID或类型新建一个对象实例,并将新建的对象的引用存入vx。22001500-new-instancev0,java.io.FileInputStream//type@0015实例化java.io.FileInputStream(类型ID表#15H条目)类型,并将其对象引用存入v0。23new-arrayvx,vy,类型ID根据类型ID或类型新建一个数组,vy存入数组的长度,vx存入数组的引用。23122500-new-arrayv2,v1,char[]//type@0025新建一个char(类型ID表#25H条目)数组,v1存入数组的长度,v2存入数组的引用。24filled-new-array{参数},类型ID根据类型ID或类型新建一个数组并通过参数填充注5。新的数组引用可以得到一个move-result-object指令,前提是执行过filled-new-array指令。2420530D0000-filled-new-array{v0,v0},[I//type@0D53新建一个int(类型ID表#D53H条目)数组,长度将为2并且2个元素将填充到v0寄存器。25filled-new-array-range{vx..vy},类型ID根据类型ID或类型新建一个数组并以寄存器范围为参数填充。新的数组引用可以得到一个move-result-object指令,前提是执行过filled-new-array指令。250306001300-filled-new-array/range{v19..v21},[B//type@0006新建一个byte(类型ID表#6条目)数组,长度将为3并且3个元素将填充到v19,v20,v21寄存器注4。26fill-array-datavx,偏移量用vx的静态数据填充数组引用。静态数据的位址是当前指令位置加偏移量的和。260625000000-fill-array-datav6,00e6//+0025用当前指令位置+25H的静态数据填充v6寄存器的数组引用。偏移量是32位的数字,静态数据的存储格式如下:0003//表类型:静态数组数据0400//每个元素的字节数(这个例子是4字节的int型)03000000//元素个数01000000//元素#0:int102000000//元素#1:int203000000//元素#2:int327throwvx抛出异常对象,异常对象的引用在vx寄存器。2700-throwv0抛出异常对象,异常对象的引用在v0寄存器。28goto目标通过短偏移量注2无条件跳转到目标。28F0-goto0005//-0010跳转到当前位置-16(hex10)的位置,0005是目标指令标签。29goto/16目标通过16位偏移量注2无条件跳转到目标。29000FFE-goto/16002f//-01f1跳转到当前位置-1F1H的位置,002f是目标指令标签。2Agoto/32目标通过32位偏移量注2无条件跳转到目标。2Bpacked-switchvx,索引表偏移量实现一个switch语句,case常量是连续的。这个指令使用索引表,vx是在表中找到具体case的指令偏移量的索引,如果无法在表中找到vx对应的索引将继续执行下一个指令(即defaultcase)。2B020C000000-packed-switchv2,000c//+000c根据v2寄存器中的值执行packedswitch,索引表的位置是当前指令位置+0CH,表如下所示:0001//表类型:packedswitch表0300//元素个数00000000//基础元素050000000:00000005//case0:+00000005070000001:00000007//case1:+00000007090000002:00000009//case2:+000000092Csparse-switchvx,查