3.3.2 空指令
指令助记符 描述
nop 代码对齐,无实际操作
3.3.3 数据操作指令
指令助记符 描述
move vA, vB 将 vA 寄存器的内容赋值给 vB,非对象类型
move/from16 vAA, vBBBB --
move/16 vAAAA, vBBBB --
move-wide vA, vB wide 后缀的指令会操作 64 位数据宽度,需使用两
个寄存器组成寄存器对。如 move-wide v0, v2 会将
v2、v3 寄存器对内容赋值给 v0、v1 寄存器对。
move-wide/from16 vAA, vBBBB --
move-wide/16 vAAAA, vBBBB --
move-object vA, vB 将 vA 寄存器的内容赋值给 vB,对象类型
move-object/from16 vAA, vBBBB --
move-object/16 vAAAA, vBBBB --
move-result vAA 必须紧跟着调用指令 invoke 后面,把调用方法的
返回值赋值给寄存器 vAA,操作非对象类型。
move-result-wide vAA --
move-result-object vAA 操作对象类型。
move-exception vAA 必须作为异常捕捉的处理块的第一条指令,把捕捉
到的异常类型对象赋值给 vAA 寄存器。
3.3.4 返回指令
指令助记符 描述
return-void 返回空类型指令。
return vAA 返回 32 位寄存器 VAA 内容,非对象类型数据。
return-wide vAA 返回 64 位内容数据,非对象类型数据。
return-object vAA 返回对象类型数据。
3.3.5 数据定义指令
指令助记符 描述
const/4 vA, #+B 将 4 位宽度的立即数带符号扩展到 32 位,赋值给
vA 寄存器。
const/16 vAA, #+BBBB 将 16 位宽度的立即数带符号扩展到 32 位, 赋值给
vA 寄存器。
const vAA, #+BBBBBBBB 将 32 位宽度的立即数赋值给 vA 寄存器。
const/high16 vAA, #+BBBB0000 将 16 位宽度的立即数右边零扩展到 32 位, 赋值给
vAA 寄存器。
const-wide/16 vAA, #+BBBB 将 16 位宽度的立即数带符号扩展到 64 位,赋给
vAA 寄存器对。
const-wide/32 vAA, #+BBBBBBBB 将 32 位宽度的立即数带符号扩展到 64 位,赋给
vAA 寄存器对。
const-wide vAA,
#+BBBBBBBBBBBBBBBB
将 64 位宽度的立即数赋给 vAA 寄存器对。
const-wide/high16 vAA,
#+BBBB000000000000
将 16 位宽度的立即数右边零扩展到 64 位, 赋值给
vAA 寄存器。
const-string vAA, string@BBBB 将字符串常量的引用赋值给 vAA 寄存器。
const-string/jumbo vAA,
string@BBBBBBBB
jumbo 后缀表示指令的寄存器的索引范围更大。
const-class vAA, type@BBBB 将一个类的引用赋值给 vAA 寄存器。
3.3.6 锁指令
指令助记符 描述
monitor-enter vAA 获取 vAA 寄存器引用的对象的同步锁。
monitor-exit vAA 释放 vAA 寄存器引用的对象的同步锁。
3.3.7 实例操作指令
指令助记符 描述
check-cast vAA, type@BBBB 把寄存器引用的对象转为指定的类型,如果不行则
会抛出一个 ClassCastException 异常。
instance-of vA, vB, type@CCCC 判断 vB 寄存器的引用对象是否可以转化为指定类
型,是则给 vA 寄存器赋 1,否则赋 0。
new-instance vAA, type@BBBB 构造一个指定类型的实例,并把引用赋给寄存器。
3.3.8 数组操作指令
指令助记符 描述
array-length vA, vB 获取 vB 引用的数组长度赋值给 vA
new-array vA, vB, type@CCCC 构造一个指定类型和大小的数组,并把引用赋值
filled-new-array {vC, vD, vE,
vF, vG}, type@BBBB
构建一个指定类型的数组,数组大小由寄存器列表
{vC,…,vG}的 长度指定,元素由寄存器列表赋值,
初始化后, 使用指令 move-result-object 获取构
建的数组的引用。
filled-new-array/range
{vCCCC .. vNNNN}, type@BBBB
寄存器列表使用连续的寄存器 vCCCC 到 vNNNN。
fill-array-data vAA,
+BBBBBBBB (with supplemental
data as specified below in
"fill-array-data-payload
Format")
使用指定的数据表来填充 vAA 指定的数组。
3.3.9 异常指令
指令助记符 描述
throw vAA 抛出一个指定类型的异常。
3.3.10 跳转指令
指令助记符 描述
goto +AA 无条件跳转到指定的指令。偏移量为 8 位宽度,且
不能为零。
goto/16 +AAAA 偏移量为 16 位宽度,且不能为零。
goto/32 +AAAAAAAA --
packed-switch vAA, +BBBBBBBB 根据+BBBBBBBB 给定的跳转偏移列表匹配 vAA 寄
存器值,跳转到指定指令。偏移表中的匹配值是有
规律递增的。
sparse-switch vAA, +BBBBBBBB 偏移表中的匹配值是无规律且可以被指定的。
if-test vA, vB, +CCCC
|- if-eq
|- if-ne
|- if-lt
|- if-ge
|- if-gt
|- if-le
条件跳转指令, 比较指定两个寄存器vA 和vB 的值,
满足条件后跳转到指定的指令。
条件:等于(eq)、不等于(ne)、小于(lt),大于
(gt),小于等于(le)、大于等于(ge)。
if-testz vAA, +BBBB
|- if-eqz
|- if-nez
|- if-ltz
|- if-gez
|- if-gtz
|- if-lez
条件跳转指令, 比较指定寄存器vAA 的值与0 大小,
满足条件跳转到指定指令。
3.3.11 比较指令
cmpkind vAA, vBB, vCC
|- cmpl-float (lt bias)
比较浮点数和长整型数的大小。 如果 vBB 寄存器大
于 vCC 寄存器,则结果为-1,相等结果则为 0,小
|- cmpg-float (gt bias)
|- cmpl-double (lt bias)
|- cmpg-double (gt bias)
|- cmp-long
于结果则为 1。结果赋给 vAA 寄存器。
3.3.12 字段操作指令
arrayop vAA, vBB, vCC
|- aget
|- aget-type
|- aput
|- aput-type
字段操作指令用来对象实例的成员变量进行读与
写操作的。分为数组字段、普通字段和静态字段。
vAA 寄存器存放读的结果或写的数据。
vBB 寄存器是数组的引用。
vCC 寄存器是数组读写元素的索引。
type 类型后缀包括 wide、object、boolean、
byte、char、short 类型。
iinstanceop vA, vB, field@CCCC
|- iget
|- iget-type
|- iput
|- iput-type
普通字段操作指令。
sstaticop vAA, field@BBBB
|- sget
|- sget-type
|- sput
|- sput-type
静态字段操作指令。
3.3.13 方法调用指令
invoke-kind {vC, vD, vE, vF,
vG}, meth@BBBB
|- invoke-virtual
|- invoke-super
|- invoke-direct
|- invoke-static
|- invoke-interface
调用指定的方法,{vC,…,vG}为传入方法的参数列
表。具体使用哪种调用方式,视方法的对象类型和
方法本身类型而定。
invoke-virtual 调用实例的虚方法,通常成员对
象实例的方法都以该指令调用。
invoke-super 调用实例的父类方法。
invoke-direct 调用直接方法,通常私有方法都以
该指令调用。
invoke-static 调用静态方法。
invoke-interface 调用接口的方法。
invoke-kind/range {vCCCC ..
vNNNN}, meth@BBBB
|- invoke-virtual/range
|- invoke-super/range
|- invoke-direct/range
|- invoke-static/range
|- invoke-interface/range
参数列表使用{vCCCC .. vNNNN}连续的寄存器列
表。
3.3.14 数据转换
unop vA, vB
|- neg-type
|- not-type
|- type-to-type
|- int-to-byte
|- int-to-char
|- int-to-short
数据类型转换指令, type 类型后缀包括 int、 long、
float、double。
3.3.15 数据运算
binop vAA, vBB, vCC
|- add-type
|- sub-type
|- mul-type
|- div-type
|- rem-type
|- and-type1
|- or-type1
|- xor-type1
|- shl-type1
|- shr-type1
|- ushr-type1
对寄存器 vBB 和寄存器 vCC 做算术运算,并把结果
赋值给 vAA。
type 类型后缀包括 int、long、float、double,。
type1 类型后缀只包括 int、long。
add:加法 sub:减法 add:乘法 div: 除法
rem:取模(%) and:与 or:或 xor:异或
shl:有符号数左移 shr:有符号数右移
ushr:无符号数右移
binop/2addr vA, vB 寄存器 vA 和寄存器 vB 做算术运算,结果赋值给寄
存器 vA。
binop/lit16 vA, vB, #+CCCC 寄存器 vB 与常量 CCCC 做算术运算, 结果赋值给 vA。
binop/lit8 vAA, vBB, #+CC 寄存器 vB 与常量 CC 做算术运算, 结果赋值给 vAA。
在以上指令中,在部分指令助记符后添加了 jumbo 后缀,这是在 Android 4.0 开始的扩
展指令,增加了寄存器和常量的取值范围。需要引起注意的是,以上指令表中形如 VA 表示
寄存器范围为 v0-v15,形如 VAA 表示寄存器范围为 v0-v255,这一点在理解指令时容易被忽
略而导致修改 smali 代码时编译出错。比如方法调用指令 invoke 未添加/range 时传入方法的
参数列表的寄存器需要在 v0-v15 范围内, 如果不在范围内需要将不合格寄存器赋值给合格
寄存器,然后再调用方法
smali指令
最新推荐文章于 2020-03-06 17:04:38 发布