Opcode 操作码(hex) |
Opcode name 操作码名称 |
Explanation 说明 |
Example 示例 |
00 |
nop |
无操作 |
0000 - nop |
01 |
move vx, vy |
移动vy的内容到vx。两个寄存器都必须在最初的256寄存器范围以内。 |
0110 - move v0, v1 移动v1寄存器中的内容到v0。 |
02 |
move/from16 vx, vy |
移动vy的内容到vx。vy可能在64K寄存器范围以内,而vx则是在最初的256寄存器范围以内。 |
0200 1900 - move/from16 v0, v25 移动v25寄存器中的内容到v0。 |
03 |
move/16 |
未知注4 |
|
04 |
move-wide |
未知注4 |
|
05 |
move-wide/from16 vx, vy |
移动一个long/double值,从vy到vx。vy可能在64K寄存器范围以内,而vx则是在最初的256寄存器范围以内。 |
0516 0000 - move-wide/from16 v22, v0 移动v0,v1寄存器中的内容到 v22,v23。 |
06 |
move-wide/16 |
未知注4 |
|
07 |
move-object vx, vy |
移动对象引用,从vy到vx。 |
0781 - move-object v1, v8 移动v8寄存器中的对象引用到v1。 |
08 |
move-object/from16 vx, vy |
移动对象引用,从vy到vx。vy可以处理64K寄存器地址,vx可以处理256寄存器地址。 |
0801 1500 - move-object/from16 v1, v21 移动v21寄存器中的对象引用到v1。 |
09 |
move-object/16 |
未知注4 |
|
0A |
move-result vx |
移动上一次方法调用的返回值到vx。 |
0A00 - move-result v0 移动上一次方法调用的返回值到v0。 |
0B |
move-result-wide vx |
移动上一次方法调用的long/double型返回值到vx,vx+1。 |
0B02 - move-result-wide v2 移动上一次方法调用的long/double型返回值到v2,v3。 |
0C |
move-result-object vx |
移动上一次方法调用的对象引用返回值到vx。 |
0C00 - move-result-object v0 移动上一次方法调用的对象引用返回值到v0。 |
0D |
move-exception vx |
当方法调用抛出异常时移动异常对象引用到vx。 |
0D19 - move-exception v25 当方法调用抛出异常时移动异常对象引用到v25。 |
0E |
return-void |
返回空值。 |
0E00 - return-void 返回值为void,即无返回值,并非返回null。 |
0F |
return vx |
返回在vx寄存器的值。 |
0F00 - return v0 返回v0寄存器中的值。 |
10 |
return-wide vx |
返回在vx,vx+1寄存器的double/long值。 |
1000 - return-wide v0 返回v0,v1寄存器中的double/long值。 |
11 |
return-object vx |
返回在vx寄存器的对象引用。 |
1100 - return-object v0 返回v0寄存器中的对象引用。 |
12 |
const/4 vx, lit4 |
存入4位常量到vx。 |
1221 - const/4 v1, #int 2 存入int型常量2到v1。目的寄存器在第二个字节的低4位,常量2在更高的4位。 |
13 |
const/16 vx, lit16 |
存入16位常量到vx。 |
1300 0A00 - const/16 v0, #int 10 存入int型常量10到v0。 |
14 |
const vx, lit32 |
存入int 型常量到vx。 |
1400 4E61 BC00 - const v0, #12345678 // #00BC614E 存入常量12345678到v0。 |
15 |
const/high16 v0, lit16 |
存入16位常量到最高位寄存器,用于初始化float值。 |
1500 2041 - const/high16 v0, #float 10.0 // #41200000 存入float常量10.0到v0。该指令最高支持16位浮点数。 |
16 |
const-wide/16 vx, lit16 |
存入int常量到vx,vx+1寄存器,扩展int型常量为long常量。 |
1600 0A00 - const-wide/16 v0, #long 10 存入long常量10到v0,v1寄存器。 |
17 |
const-wide/32 vx, lit32 |
存入32位常量到vx,vx+1寄存器,扩展int型常量到long常量。 |
1702 4e61 bc00 - const-wide/32 v2, #long 12345678 // #00bc614e 存入long常量12345678到v2,v3寄存器。 |
18 |
const-wide vx, lit64 |
存入64位常量到vx,vx+1寄存器。 |
1802 874b 6b5d 54dc 2b00- const-wide v2, #long 12345678901234567 // #002bdc545d6b4b87 存入long常量12345678901234567到v2,v3寄存器。 |
19 |
const-wide/high16 vx, lit16 |
存入16位常量到最高16位的vx,vx+1寄存器,用于初始化double 值。 |
1900 2440 - const-wide/high16 v0, #double 10.0 // #402400000 存入double常量10.0到v0,v1。 |
1A |
const-string vx, 字符串ID |
存入字符串常量引用到vx,通过字符串ID或字符串。 |
1A08 0000 - const-string v8, "" // string@0000 存入string@0000(字符串表#0条目)的引用到v8。 |
1B |
const-string-jumbo |
未知注4 |
|
1C |
const-class vx, 类型ID |
存入类对象常量到vx,通过类型ID或类型(如Object.class)。 |
1C00 0100 - const-class v0, Test3 // type@0001 存入Test3.class(类型ID表#1条目)的引用到v0。 |
1D |
monitor-enter vx |
获得vx寄存器中的对象引用的监视器。 |
1D03 - monitor-enter v3 获得v3寄存器中的对象引用的监视器。 |
1E |
monitor-exit |
释放vx寄存器中的对象引用的监视器。 |
1E03 - monitor-exit v3 释放v3寄存器中的对象引用的监视器。 |
1F |
check-cast vx, 类型ID |
检查vx寄存器中的对象引用是否可以转换成类型ID对应类型的实例。如不可转换,抛出ClassCastException 异常,否则继续执行。 |
1F04 0100 - check-cast v4, Test3 // type@0001 检查v4寄存器中的对象引用是否可以转换成Test3(类型ID表#1条目)的实例。 |
20 |
instance-of vx, vy,类型ID |
检查vy寄存器中的对象引用是否是类型ID对应类型的实例,如果是,vx存入非0值,否则vx存入0。 |
2040 0100 - instance-of v0, v4, Test3 // type@0001 检查v4寄存器中的对象引用是否是Test3(类型ID表#1条目)的实例。如果是,v0存入非0值,否则v0存入0。 |
21 |
array-length vx, vy |
计算vy寄存器中数组引用的元素长度并将长度存入vx。 |
2111 - array-length v0, v1 计算v1寄存器中数组引用的元素长度并将长度存入v0。 |
22 |
new-instance vx, 类型ID |
根据类型ID或类型新建一个对象实例,并将新建的对象的引用存入vx。 |
2200 1500 - new-instance v0, java.io.FileInputStream // type@0015 实例化java.io.FileInputStream(类型ID表#15H条目)类型,并将其对象引用存入v0。 |
23 |
new-array vx, vy,类型ID |
根据类型ID或类型新建一个数组,vy存入数组的长度,vx存入数组的引用。 |
2312 2500 - new-array v2, v1, char[] // type@0025 新建一个char(类型ID表#25H条目)数组,v1存入数组的长度,v2存入数组的引用。 |
24 |
filled-new-array { 参数}, 类型ID |
根据类型ID或类型新建一个数组并通过参数填充注5。新的数组引用可以得到一个move-result-object指令,前提是执行过filled-new-array 指令。 |
2420 530D 0000 - filled-new-array {v0,v0},[I // type@0D53 新建一个int(类型ID表#D53H条目)数组,长度将为2并且2个元素将填充到v0寄存器。 |
25 |
filled-new-array-range {vx..vy}, 类型ID |
根据类型ID或类型新建一个数组并以寄存器范围为参数填充。新的数组引用可以得到一个move-result-object指令,前提是执行过filled-new-array 指令。 |
2503 0600 1300 - filled-new-array/range {v19..v21}, [B // type@0006 新建一个byte(类型ID表#6条目)数组,长度将为3并且3个元素将填充到v19,v20,v21寄存器注4。 |
26 |
fill-array-data vx, 偏移量 |
用vx的静态数据填充数组引用。静态数据的位址是当前指令位置加偏移量的和。 |
2606 2500 0000 - fill-array-data v6, 00e6 // +0025 用当前指令位置+25H的静态数据填充v6寄存器的数组引用。偏移量是32位的数字,静态数据的存储格式如下: 0003 // 表类型:静态数组数据 0400 // 每个元素的字节数(这个例子是4字节的int型) 0300 0000 // 元素个数 0100 0000 // 元素 #0:int 1 0200 0000 // 元素 #1:int 2 0300 0000 // 元素 #2:int 3 |
27 |
throw vx |
抛出异常对象,异常对象的引用在vx寄存器。 |
2700 - throw v0 抛出异常对象,异常对象的引用在v0寄存器。 |
28 |
goto 目标 |
通过短偏移量注2无条件跳转到目标。 |
28F0 - goto 0005 // -0010 跳转到当前位置-16(hex 10)的位置,0005是目标指令标签。 |
29 |
goto/16目标 |
通过16位偏移量注2无条件跳转到目标。 |
2900 0FFE - goto/16 002f // -01f1 跳转到当前位置-1F1H的位置,002f是目标指令标签。 |
2A |
goto/32目标 |
通过32位偏移量注2无条件跳转到目标。 |
|
2B |
packed-switch vx, 索引表偏移量 |
实现一个switch 语句,case常量是连续的。这个指令使用索引表,vx是在表中找到具体case的指令偏移量的索引,如果无法在表中找到vx对应的索引将继续执行下一个指令(即default case)。 |
2B02 0C00 0000 - packed-switch v2, 000c // +000c 根据v2寄存器中的值执行packed switch,索引表的位置是当前指令位置+0CH,表如下所示: 0001 // 表类型:packed switch表 0300 // 元素个数 0000 0000 // 基础元素 0500 0000 0: 00000005 // case 0: +00000005 0700 0000 1: 00000007 // case 1: +00000007 0900 0000 2: 00000009 // case 2: +00000009 |
2C |
sparse-switch vx, 查询表偏移量 |
实现一个switch 语句,case常量是非连续的。这个指令使用查询表,用于表示case常量和每个case常量的偏移量。如果vx无法在表中匹配将继续执行下一个指令(即default case)。 |
2C02 0c00 0000 - sparse-switch v2, 000c // +000c 根据v2寄存器中的值执行sparse switch ,查询表的位置是当前指令位置+0CH,表如下所示: 0002 // 表类型:sparse switch表 0300 // 元素个数 9cff ffff // 第一个case常量: -100 fa00 0000 // 第二个case常量: 250 e803 0000 // 第三个case常量: 1000 0500 0000 // 第一个case常量的偏移量: +5 0700 0000 // 第二个case常量的偏移量: +7 0900 0000 // 第三个case常量的偏移量: +9 |
2D |
cmpl-float vx, vy, vz |
比较vy和vz的float值并在vx存入int型返回值注3。 |
2D00 0607 - cmpl-float v0, v6, v7 比较v6和v7的float值并在v0存入int型返回值。非数值默认为小于。如果参数为非数值将返回-1。 |
2E |
cmpg-float vx, vy, vz |
比较vy和vz的float值并在vx存入int型返回值注3。 |
2E00 0607 - cmpg-float v0, v6, v7 比较v6和v7的float值并在v0存入int型返回值。非数值默认为大于。如果参数为非数值将返回1。 |
2F |
cmpl-double vx, vy, vz |
比较vy和vz注2的double值并在vx存入int型返回值注3。 |
2F19 0608 - cmpl-double v25, v6, v8 比较v6,v7和v8,v9的double值并在v25存入int型返回值。非数值默认为小于。如果参数为非数值将返回-1。 |
30 |
cmpg-double vx, vy, vz |
比较vy和vz |
smali语法中文版
最新推荐文章于 2024-09-19 20:16:28 发布
本文介绍了smali语法,包括Double和long值的寄存器占用、偏移量的计算方式、比较操作的返回值规则,以及Android编译中参数表的特殊处理。特别提到,某些指令仅适用于ODEX文件,具有一定的安全性风险。
摘要由CSDN通过智能技术生成
这是学习Smali重中之中,不过现在有些反编译的软件已经存在相应的插件,可以直接看到这些操作码名称的中文解释(如:Android killer),但是对其进行学习还是非常有必要的。以下是smali语法的表格: