Dalvik 寄存器

寄存器命名法

Dalvik 字节码

Dalvik 指令集

Dalvik 指令在调用格式上模仿了 C 语言的调用约定。Dalvik 指令的语法与助记符有如下特点。

  • 参数采用从目标 (detination) 到 (source)的方式
  • 根据字节码大小与类型的不同, 为一些字节码添加了名称后缀以消除歧义
    • 32 位常规类型的字节码未添加任何后缀。
    • 64 位常规类型的字节码添加 -wide 后缀。
    • 对特殊类型的字节码, 根据具体类型添加后缀, 可以使 -boolean、-byte、-char、-short、-int、-long、-float、-double、-object、-string、-class、-void中的一个
  • 根据字节码布局的选项不同, 为一些字节码添加了字节码后缀以消除歧义。这些后缀通过字节码主名称后添加斜杠来分割。
  • 在指令集的描述中, 宽度值中的每个字母 都表示 4 位的宽度。

空操作指令

空操作指令的助记符为 nop, 它的值为 00。nop 指令通常用于对齐代码, 不进行实际操作。

数据操作指令

数据操作指令为 move, 其原型为 move destination, source。根据字节码大小与类型的不同, move 指令有不同的后缀, 如下:

指令 描述
move vA, vB 指令用于将 vB 寄存器的值赋值给 vA 寄存器,
源寄存器和目的寄存器都是 4 位
move/from16 vAA, vBBBB 指令用于将 vBBBB 寄存器的值赋值给 vAA 寄存器,
源寄存器为 16 位, 目的寄存器为 8 位
move/16 vAAAA, vBBBB 指令用于将 vBBBB 寄存器的值赋值给 vAAAA 寄存器,
源寄存器和目的寄存器都是 16 位
move-wide vA, vB 指令用于为 4 位的寄存器对赋值, 源寄存器和目的寄存器都是 4 位
move-wide/from16 vAA, vBBBB 与 move-wide 相同
move-wide/16 vAA, vBBBB 与 move-wide 相同
move-object vA,vB 指令用于为对象赋值, 源寄存器和目的寄存器都是 4 位
move-object/from16 vAA, vBBBB 指令用于为对象赋值, 源寄存器为 16 位, 目的寄存器为 8 位
move-object/16 vAAAA, vBBBB 指令用于为对象赋值, 源寄存器和目的寄存器都是 16 位
move-result vAA 指令用于将上一个 invoke 类型指令操作的单字非对象结果赋给 vAA 寄存器
move-result-wide vAA 指令用于将上一个 invoke 类型指令操作的双字非对象结果赋给 vAA 寄存器
move-result-object vAA 指令用于将上一个 invoke 类型指令操作的对象结果赋给 vAA 寄存器
move-exception vAA 指令用于将一个在运行时发生的异常保存到 vAA 寄存器中。
这条指令必须在异常发生时由异常处理器使用, 否则指令无效

返回指令

返回指令是指函数结束时运行的最后一条指令, 它的基础字节码为 return, 如下:

指令 描述
return-void 指令表示函数从一个 void 方法返回
return vAA 指令表示函数返回一个 32 位非对象类型的值, 返回值寄存器为 8 位的寄存器 vAA
return-wide vAA 指令表示函数返回一个 64 位非对象类型的值, 返回值寄存器为 8 位的寄存器对 vAA
return-object vAA 指令表示函数返回一个对象类型的值, 返回值为 8 位的寄存器 vAA

数据定义指令

数据定义指令用来定义程序中用到的常量、字符串、类等数据, 它的基础字节码为 const, 如下:

指令 描述
const/4 vA,#+B 指令用于将数值符号扩展为 32 位后赋给寄存器 vA
const/16 vAA,#+BBBB 指令用于将数值符号扩展为 32 位后赋给寄存器 vAA
const vAA,#+BBBBBBBB 指令用于将数值赋给寄存器 vAA
const/high16 vAA,#+BBBB0000 指令用于将数值右边零扩展为 32 位后赋给寄存器 vAA
const-wide/16 vAA,#+BBBB 指令用于将数值扩展为 64 位后赋给寄存器对 vAA
const-wide/32 vAA,#+BBBBBBBB 指令用于将数值扩展为 64 位后赋给寄存器对 vAA
const-wide vAA,#+BBBBBBBBBBBBBBBB 指令用于将数值赋给寄存器对 vAA
const-wide/hight16 vAA,#+BBBB000000000000 指令用于将数值右边零扩展为 64 位后赋给寄存器对 vAA
const-string vAA,string@BBBB 指令用于通过字符串索引构造一个字符串并赋给寄存器 vAA
const-string/jumbo vAA,string@BBBBBBBB 指令用于通过字符串索引(较大)构造一个字符串并赋给寄存器 vAA
const-class vAA,type@BBBB 指令用于通过类型索引获取一个类引用并赋给寄存器 vAA
const-class/jumbo vAAAA,type@BBBBBBBB 指令用于通过类型索引获取一个类引用并赋给寄存器 vAA
(这条指令占用两个字节, 值为 0x00ff)

锁指令

锁指令多用在多线程中对同一对象的操作中, Dalvik 指令集中提供了如下两条锁指令:

指令 描述
monitor-enter vAA 为指定的对象获取锁
monitor-exit vAA 释放指定对象的锁

实例操作指令

与实例相关的操作包括实例的类型转换、检查及创建等。如下:

指令 描述
check-cast vAA,type@BBBB 指令用于将 vAA 寄存器中的对象引用转换成指定的类型,
如果失败会抛出 ClassCastException 异常,
如果类型 B 指定的是基本类型,
对于非基本类型的 A 来说, 运行时始终会失败。
instance-of vA,vB,type@CCCC 指令用于判断 vB 寄存器中的对象是否可以转换成指定的类型,
如果可以 vA 赋给 1, 否则赋给 0。
new-instance vAA,type@BBBB 指令用于构造一个指定类型对象的新实例, 并将对象引用赋给 vAA,
类型符 type 指定的类型不是数组。
check-cast/jumbo vAAAA,type@BBBBBBBB 同 check-cast vAA,type@BBBB ,
只是寄存器值和指令的索引取值返回更大 (android 4.0 新增)
instance-of/jumbo vAAAA,vBBBB,type@CCCCCCCC 同 instance-of vA,vB,type@CCCC ,
只是寄存器值和指令的索引取值返回更大 (android 4.0 新增)
new-instance/jumbo vAAAA,type@BBBBBBBB 同 new-instance vAA,type@BBBB ,
只是寄存器值和指令的索引取值返回更大 (android 4.0 新增)

数组操作指令

数组操作包括获取数组长度、新建数组、数组赋值、数组元素取值与赋值等操作。如下:

指令 描述
array-length vA, vB 获取给定 VB 寄存器中数组的长度并将值赋给 vA 寄存器
new-array vA, vB, type@CCCC 构造指定类型 (type@CCCC) 和大小 (vB) 的数组, 并将值赋给 vA
filled-new-array {vC, vD, vE, vF, vG}, type@BBBB 构造指定类型 (type@BBBB) 和大小 (vA) 的数组并填充数组内容。
vA 寄存器是隐含使用的, 除了指定数组的大小外还指定了参数的个数, vC ~ vG 是使用到的参数寄存器序列
filled-new-array/range {vCCCC .. vNNNN}, type@BBBB 指令功能同 filled-new-array {vC,vD,vE,vF,vG},type@BBBB,
只是参数寄存器使用 range 字节码后缀指定了取值范围,
vC 是第一个参数寄存器, N = A + C - 1
fill-array-data vAA, +BBBBBBBB 用指定的数据来填充数组, vAA 为数组引用,
引用必须为基础类型的数组, 再指令后面会紧跟一个数据表
new-array/jumbo vAAAA, vBBBB, type@CCCCCCCC 同 new-array vA,vB,type@CCCC ,
只是寄存器值和指令的索引取值返回更大 (android 4.0 新增)
filled-new-array/jumbo {vCCCC .. vNNNN}, type@BBBBBBBB 同 filled-new-array/range {vCCCC … vNNNN},type@BBBB ,
只是索引取值返回更大 (android 4.0 新增)
arrayop vAA, vBB, vCC 对 vBB 寄存器指定的数组元素进行取值和赋值,
vCC 指定数组元素索引, vAA 用来存放读取的或需要设置的数组元素的值,
读取元素使用 aget 类指令, 元素赋值使用 aput 类指令,
根据数组中存储的类型指令后面会紧跟不同的指令后缀, 指令列表有
( aget , aget-wide , aget-object ,
aget-boolean , aget-byte , aget-char ,
aget-short , aput , aput-wide ,
aput-object , aput-boolean ,
aput-byte , aput-char , aput-short )

异常指令