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 ) |

