logo资料库

Smali指令中文手册.pdf

第1页 / 共18页
第2页 / 共18页
第3页 / 共18页
第4页 / 共18页
第5页 / 共18页
第6页 / 共18页
第7页 / 共18页
第8页 / 共18页
资料共18页,剩余部分请下载后查看
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,查询表偏移量实现一个switch语句,case常量是非连续的。这个指令使用查询表,用于表示case常量和每个case常量的偏移量。如果vx无法在表中匹配将继续执行下一个指令(即defaultcase)。2C020c000000-sparse-switchv2,000c//+000c根据v2寄存器中的值执行sparseswitch,查询表的位置是当前指令位置+0CH,表如下所示:0002//表类型:sparseswitch表0300//元素个数9cffffff//第一个case常量:-100fa000000//第二个case常量:250e8030000//第三个case常量:100005000000//第一个case常量的偏移量:+507000000//第二个case常量的偏移量:+709000000//第三个case常量的偏移量:+92Dcmpl-floatvx,vy,vz比较vy和vz的float值并在vx存入int型返回值注3。2D000607-cmpl-floatv0,v6,v7比较v6和v7的float值并在v0存入int型返回值。非数值默认为小于。如果参数为非数值将返回-1。2Ecmpg-floatvx,vy,vz比较vy和vz的float值并在vx存入int型返回值注3。2E000607-cmpg-floatv0,v6,v7比较v6和v7的float值并在v0存入int型返回值。非数值默认为大于。如果参数为非数值将返回1。2Fcmpl-doublevx,vy,vz比较vy和vz注2的double值并在vx存入int型返回值注3。2F190608-cmpl-doublev25,v6,v8比较v6,v7和v8,v9的double值并在v25存入int型返回值。非数值默认为小于。如果参数为非数值将返回-1。30cmpg-doublevx,vy,vz比较vy和vz注2的double值并在vx存入int型返回值注3。3000080A-cmpg-doublev0,v8,v10比较v8,v9和v10,v11的double值并在v0存入int型返回值。非数值默认为大于。如果参数
为非数值将返回1。31cmp-longvx,vy,vz比较vy和vz的long值并在vx存入int型返回值注3。31000204-cmp-longv0,v2,v4比较v2和v4的long值并在v0存入int型返回值。32if-eqvx,vy,目标如果vx==vy注2,跳转到目标。vx和vy是int型值。32b36600-if-eqv3,v11,0080//+0066如果v3==v11,跳转到当前位置+66H。0080是目标指令标签。33if-nevx,vy,目标如果vx!=vy注2,跳转到目标。vx和vy是int型值。33A31000-if-nev3,v10,002c//+0010如果v3!=v10,跳转到当前位置+10H。002c是目标指令标签。34if-ltvx,vy,目标如果vx=vy注2,跳转到目标。vx和vy是int型值。35101B00-if-gev0,v1,002b//+001b如果v0>=v1,跳转到当前位置+1BH。002b是目标指令标签。36if-gtvx,vy,目标如果vx>vy注2,跳转到目标。vx和vy是int型值。36101B00-if-gev0,v1,002b//+001b如果v0>v1,跳转到当前位置+1BH。002b是目标指令标签。37if-levx,vy,目标如果vx<=vy注2,跳转到目标。vx和vy是int型值。37560B00-if-lev6,v5,0144//+000b如果v6<=v5,跳转到当前位置+0BH。0144是目标指令标签。38if-eqzvx,目标如果vx==0注2,跳转到目标。vx是int型值。38021900-if-eqzv2,0038//+0019如果v2==0,跳转到当前位置+19H。0038是目标指令标签。39if-nezvx,目标如果vx!=0注2,跳转到目标。39021200-if-nezv2,0014//+0012如果v2!=0,跳转到当前位置+18(hex12)。0014是目标指令标签。3Aif-ltzvx,目标如果vx<0注2,跳转到目标。3A001600-if-ltzv0,002d//+0016如果v0<0,跳转到当前位置+16H。002d是目标指令标签。3Bif-gezvx,目标如果vx>=0注2,跳转到目标。3B001600-if-gezv0,002d//+0016如果v0>=0,跳转到当前位置+16H。002d是目标指令标签。3Cif-gtzvx,目标如果vx>0注2,跳转到目标。3C001D00-if-gtzv0,004a//+001d如果v0>0,跳转到当前位置+1DH。004a是目标指令标签。3Dif-lezvx,目标如果vx<=0注2,跳转到目标。3D001D00-if-lezv0,004a//+001d如果v0<=0,跳转到当前位置+1DH。004a是目标指令标签。
3Eunused_3E未使用3Funused_3F未使用40unused_40未使用41unused_41未使用42unused_42未使用43unused_43未使用44agetvx,vy,vz从int数组获取一个int型值到vx,对象数组的引用位于vy,需获取的元素的索引位于vz。44070306-agetv7,v3,v6从数组获取一个int型值到v7,对象数组的引用位于v3,需获取的元素的索引位于v6。45aget-widevx,vy,vz从long/double数组获取一个long/double值到vx,vx+1,数组的引用位于vy,需获取的元素的索引位于vz。45050104-aget-widev5,v1,v4从long/double数组获取一个long/double值到v5,vx6,数组的引用位于v1,需获取的元素的索引位于v4。46aget-objectvx,vy,vz从对象引用数组获取一个对象引用到vx,对象数组的引用位于vy,需获取的元素的索引位于vz。46020200-aget-objectv2,v2,v0从对象引用数组获取一个对象引用到v2,对象数组的引用位于v2,需获取的元素的索引位于v0。47aget-booleanvx,vy,vz从boolean数组获取一个boolean值到vx,数组的引用位于vy,需获取的元素的索引位于vz。47000001-aget-booleanv0,v0,v1从boolean数组获取一个boolean值到v0,数组的引用位于v0,需获取的元素的索引位于v1。48aget-bytevx,vy,vz从byte数组获取一个byte值到vx,数组的引用位于vy,需获取的元素的索引位于vz。48000001-aget-bytev0,v0,v1从byte数组获取一个byte值到v0,数组的引用位于v0,需获取的元素的索引位于v1。49aget-charvx,vy,vz从char数组获取一个char值到vx,数组的引用位于vy,需获取的元素的索引位于vz。49050003-aget-charv5,v0,v3从char数组获取一个char值到v5,数组的引用位于v0,需获取的元素的索引位于v3。4Aaget-shortvx,vy,vz从short数组获取一个short值到vx,数组的引用位于vy,需获取的元素的索引位于vz。4A000001-aget-shortv0,v0,v1从short数组获取一个short值到v0,数组的引用位于v0,需获取的元素的索引位于v1。4Baputvx,vy,vz将vx的int值作为元素存入int数组,数组的引用位于vy,元素的索引位于vz。4B000305-aputv0,v3,v5将v0的int值作为元素存入int数组,数组的引用位于v3,元素的索引位于v5。4Caput-widevx,vy,vz将vx,vx+1的double/long值作为元素存入double/long数组,数组的引用位于vy,元素的索引位于vz。4C050104-aput-widev5,v1,v4将v5,v6的double/long值作为元素存入double/long数组,数组的引用位于v1,元素的索引位于v4。4Daput-objectvx,vy,vz将vx的对象引用作为元素存入对象引用数组,数组的引用位于vy,元素的索引位于vz。4D020100-aput-objectv2,v1,v0将v2的对象引用作为元素存入对象引用数组,数组的引用位于v1,元素的索引位于v0。4Eaput-booleanvx,vy,vz将vx的boolean值作为元素存入boolean数组,数组的引用位于vy,元素的索引位于vz。4E010002-aput-booleanv1,v0,v2将v1的boolean值作为元素存入boolean数组,数组的引用位于v0,元素的索引位于v2。4Faput-bytevx,vy,vz将vx的byte值作为元素存入byte数组,数组的引用位于vy,元4F020001-aput-bytev2,v0,v1将v2的byte值作为元素存入byte数组,数组
素的索引位于vz。的引用位于v0,元素的索引位于v1。50aput-charvx,vy,vz将vx的char值作为元素存入char数组,数组的引用位于vy,元素的索引位于vz。50030001-aput-charv3,v0,v1将v3的char值作为元素存入char数组,数组的引用位于v0,元素的索引位于v1。51aput-shortvx,vy,vz将vx的short值作为元素存入short数组,数组的引用位于vy,元素的索引位于vz。51020001-aput-shortv2,v0,v1将v2的short值作为元素存入short数组,数组的引用位于v0,元素的索引位于v1。52igetvx,vy,字段ID根据字段ID读取实例的int型字段到vx,vy寄存器中是该实例的引用。52100300-igetv0,v1,Test2.i6:I//field@0003读取int型字段i6(字段表#3条目)到v0,v1寄存器中是Test2实例的引用。53iget-widevx,vy,字段ID根据字段ID读取实例的double/long型字段到vx,vx+1注1,vy寄存器中是该实例的引用。53200400-iget-widev0,v2,Test2.l0:J//field@0004读取long型字段l0(字段表#4条目)到v0,v1,v2寄存器中是Test2实例的引用。54iget-objectvx,vy,字段ID根据字段ID读取一个实例的对象引用字段到vx,vy寄存器中是该实例的引用。iget-objectv1,v2,LineReader.fis:Ljava/io/FileInputStream;//field@0002读取FileInputStream对象引用字段fis(字段表#2条目)到v1,v2寄存器中是LineReader实例的引用。55iget-booleanvx,vy,字段ID根据字段ID读取实例的boolean型字段到vx,vy寄存器中是该实例的引用。55FC0000-iget-booleanv12,v15,Test2.b0:Z//field@0000读取boolean型字段b0(字段表#0条目)到v12,v15寄存器中是Test2实例的引用。56iget-bytevx,vy,字段ID根据字段ID读取实例的byte型字段到vx,vy寄存器中是该实例的引用。56320100-iget-bytev2,v3,Test3.bi1:B//field@0001读取byte型字段bi1(字段表#1条目)到v2,v3寄存器中是Test2实例的引用。57iget-charvx,vy,字段ID根据字段ID读取实例的char型字段到vx,vy寄存器中是该实例的引用。57200300-iget-charv0,v2,Test3.ci1:C//field@0003读取char型字段bi1(字段表#3条目)到v0,v2寄存器中是Test2实例的引用。58iget-shortvx,vy,字段ID根据字段ID读取实例的short型字段到vx,vy寄存器中是该实例的引用。58300800-iget-shortv0,v3,Test3.si1:S//field@0008读取short型字段si1(字段表#8条目)到v0,v3寄存器中是Test2实例的引用。59iputvx,vy,字段ID根据字段ID将vx寄存器的值存入实例的int型字段,vy寄存器中是该实例的引用。59200200-iputv0,v2,Test2.i6:I//field@0002将v0寄存器的值存入实例的int型字段i6(字段表#2条目),v2寄存器中是Test2实例的引用。5Aiput-widevx,vy,字段ID根据字段ID将vx,vx+1寄存器的值存入实例的double/long型字段,vy寄存器中是该实例的引用。5A200000-iput-widev0,v2,Test2.d0:D//field@0000将v0,v1寄存器的值存入实例的double型字段d0(字段表#0条目),v2寄存器中是Test2实例的引用。
5Biput-objectvx,vy,字段ID根据字段ID将vx寄存器的值存入实例的对象引用字段,vy寄存器中是该实例的引用。5B200000-iput-objectv0,v2,LineReader.bis:Ljava/io/BufferedInputStream;//field@0000将v0寄存器的值存入实例的对象引用字段bis(字段表#0条目),v2寄存器中是BufferedInputStream实例的引用。5Ciput-booleanvx,vy,字段ID根据字段ID将vx寄存器的值存入实例的boolean型字段,vy寄存器中是该实例的引用。5C300000-iput-booleanv0,v3,Test2.b0:Z//field@0000将v0寄存器的值存入实例的boolean型字段b0(字段表#0条目),v3寄存器中是Test2实例的引用。5Diput-bytevx,vy,字段ID根据字段ID将vx寄存器的值存入实例的byte型字段,vy寄存器中是该实例的引用。5D200100-iput-bytev0,v2,Test3.bi1:B//field@0001将v0寄存器的值存入实例的byte型字段bi1(字段表#1条目),v2寄存器中是Test2实例的引用。5Eiput-charvx,vy,字段ID根据字段ID将vx寄存器的值存入实例的char型字段,vy寄存器中是该实例的引用。5E200300-iput-charv0,v2,Test3.ci1:C//field@0003将v0寄存器的值存入实例的char型字段ci1(字段表#3条目),v2寄存器中是Test2实例的引用。5Fiput-shortvx,vy,字段ID根据字段ID将vx寄存器的值存入实例的short型字段,vy寄存器中是该实例的引用。5F210800-iput-shortv1,v2,Test3.si1:S//field@0008将v0寄存器的值存入实例的short型字段si1(字段表#8条目),v2寄存器中是Test2实例的引用。60sgetvx,字段ID根据字段ID读取静态int型字段到vx。60000700-sgetv0,Test3.is1:I//field@0007读取Test3的静态int型字段is1(字段表#7条目)到v0。61sget-widevx,字段ID根据字段ID读取静态double/long型字段到vx,vx+1。61000500-sget-widev0,Test2.l1:J//field@0005读取Test2的静态long型字段l1(字段表#5条目)到v0,v1。62sget-objectvx,字段ID根据字段ID读取静态对象引用字段到vx。62010C00-sget-objectv1,Test3.os1:Ljava/lang/Object;//field@000c读取Object的静态对象引用字段os1(字段表#CH条目)到v1。63sget-booleanvx,字段ID根据字段ID读取静态boolean型字段到vx。63000C00-sget-booleanv0,Test2.sb:Z//field@000c读取Test2的静态boolean型字段sb(字段表#CH条目)到v0。64sget-bytevx,字段ID根据字段ID读取静态byte型字段到vx。64000200-sget-bytev0,Test3.bs1:B//field@0002读取Test3的静态byte型字段bs1(字段表#2条目)到v0。65sget-charvx,根据字段ID读取静态char型字65000700-sget-charv0,Test3.cs1:C
分享到:
收藏