Dalvik 可执行指令格式

本页列出了 Dalvik 可执行文件 (DEX) 格式和 Dalvik 字节码使用的指令格式。本页内容需要结合字节码参考文档使用。

按位描述

格式表的第一列列出了格式的按位布局。它由一个或多个空格分隔的“单词”组成,每个单词描述一个 16 位代码单元。指令字中的每个字符表示四位,按照从高位到低位的顺序进行排列,并使用竖线 (“|”) 分隔以便于用户分辨。从“A”开始的大写字母用于表示格式中的字段,这些字段随后由语法列做进一步定义。“op”一词用于表示格式内八位操作码的位置。带斜划的零(“Ø”)用于表示所有在指示位置的位必须为零。

在大部分情况下,字母按照代码单元的顺序进行排列,代码单元中按照从低位到高位的顺序进行排序。但也存在例外情况,为了让含义相近的部分在不同的指令格式中使用相同的命名,可能也会改变顺序。这些情况在格式说明中进行了明确说明。

例如,“B|A|op CCCC”格式表示其包含两个 16 位代码单元。第一个字由低八位中的操作码和高八位中的两个四位值组成;第二个字由单个 16 位值组成。

格式 ID

格式表中的第二列表示格式的短标识符,用于在其他文档和代码中识别该格式。

大多数格式 ID 包含三个字符:前两个是十进制数,最后一个是字母。第一个数字表示该格式的 16 位代码单元的数量。第二个数字表示格式所含寄存器的数量上限(因为某些格式使用的寄存器数量是可变的),特殊标识“r”表示编码了一系列寄存器。最后一个字母以半助记符的形式表示该格式编码的任何其他数据类型。例如,“21t”格式的长度为 2,包含一个寄存器引用,另外还包含一个分支目标。

建议使用的静态链接格式有一个额外的“s”后缀,因此加上后缀一共是四个字符。同样,建议使用的“内联”链接格式也有一个额外的“i”后缀。(在这种情况下,内联链接与静态链接类似,但它与机器实现具有更直接的联系。)最后,建议使用的格式中有几个较为特别(例如“20bc”),它们包含两个数据块,都分别体现在格式 ID 中。

类型代码字母的完整列表如下。请注意,由于格式上的差异,部分形式的大小可能有所不同:

Mnemonic 位数 含义
b 8 有符号立即数(字节)
c 16、32 常量池索引
f 16 f常量(仅对静态链接格式有效)
h 16 有符号立即数 hat(32 位或 64 位值的高阶位,低阶位全为 0
i 32 有符号立即数(整型)或 32 位浮点数
l 64 有符号立即数(长整型)或 64 位双精度浮点数l
m 16 方法常量(仅对静态链接格式有效)
n 4 有符号立即数(半字节)
s 16 有符号立即数(短整型)
t 8、16、32 分支目标
x 0 无额外数据

语法

格式表的第三列指出了指令中所使用的人类可识别的语法。每个指令以命名的操作码开始,后面可选择使用一个或多个参数,并且参数之间用逗号分隔。

如果一个参数对应第一列中的一个字段,相应字段的字母将出现在语法中,字母每重复一次即代表字段中的四位。例如,第一列中标记为“BB”的八位字段在语法列中也将标记为“BB”。

命名寄存器的参数所采用的形式为“vX”。选择“v”而不是更常用的“r”作为前缀,是因为这样可避免与可能会在其上实现 Dalvik 可执行文件格式的(非虚拟)架构(其寄存器使用“r”作为前缀)出现冲突。(也就是说,我们可以直截了当地同时讨论虚拟和实际寄存器。)

表示字面量值的参数所采用的形式为“#+X”。有些格式在表示字面量时,仅记录其非零高阶位;对于这类字面量,语法中会明确写出 0,但是在按位表示法中会省略 0。

表示相对指令地址偏移量的参数所采用的形式为“+X”。

表示字面常量池索引的参数所采用的形式为“kind@X”,其中“kind”表示所引用的常量池的种类。相关规则明确规定每个使用此类格式的操作码只允许使用一种常量;请查看操作码参考文档,找出对应关系。常量池的种类包括“string”(字符串池索引)、“type”(类型池索引)、“field”(字段池索引)、“meth”(方法池索引)和“site”(调用点索引)。

此外还可使用一些建议的可选形式,它们与常量池索引的表示法类似,表示预链接的偏移量或索引。可以使用两种类型的建议预链接值:vtable 偏移(表示为“vtaboff”)和字段偏移(表示为“fieldoff”)。

如果格式值并非明确地包含在语法中,而是选择使用某种变体,那么每个变体都以“[X=N]”(例如:“[A=2]”)为前缀来表示对应关系。

格式

格式 ID 语法 包含的重要操作码
不适用 00x N/A 用于未使用的操作码的伪格式;建议用作断点操作码的标称格式
ØØ|op 10x op  
B|A|op 12x op vA, vB  
11n op vA, #+B  
AA|op 11x op vAA  
10t op +AA goto
ØØ|op AAAA 20t op +AAAA goto/16
AA|op BBBB 20bc op AA, kind@BBBB 静态确定的验证错误的建议格式;其中,A 表示错误类型,B 表示类型适当的表的索引(例如,出现“不存在这种方法”错误时的方法引用)
AA|op BBBB 22x op vAA, vBBBB  
21t op vAA, +BBBB  
21s op vAA, #+BBBB  
21h op vAA, #+BBBB0000
op vAA, #+BBBB000000000000
 
21c op vAA, type@BBBB
op vAA, field@BBBB
op vAA, method_handle@BBBB
op vAA, proto@BBBB
op vAA, string@BBBB
check-cast
const-class
const-method-handle
const-method-type
const-string
AA|op CC|BB 23x op vAA, vBB, vCC  
22b op vAA, vBB, #+CC  
B|A|op CCCC 22t op vA, vB, +CCCC  
22s op vA, vB, #+CCCC  
22c op vA, vB, type@CCCC
op vA, vB, field@CCCC
instance-of
22cs op vA, vB, fieldoff@CCCC 22c 格式的静态链接字段访问指令的建议格式
ØØ|op AAAAlo AAAAhi 30t op +AAAAAAAA goto/32
ØØ|op AAAA BBBB 32x op vAAAA, vBBBB  
AA|op BBBBlo BBBBhi 31i op vAA, #+BBBBBBBB  
31t op vAA, +BBBBBBBB  
31c op vAA, string@BBBBBBBB const-string/jumbo
A|G|op BBBB F|E|D|C 35c [A=5] op {vC, vD, vE, vF, vG}, meth@BBBB
[A=5] op {vC, vD, vE, vF, vG}, site@BBBB
[A=5] op {vC, vD, vE, vF, vG}, type@BBBB
[A=4] op {vC, vD, vE, vF}, kind@BBBB
[A=3] op {vC, vD, vE}, kind@BBBB
[A=2] op {vC, vD}, kind@BBBB
[A=1] op {vC}, kind@BBBB
[A=0] op {}, kind@BBBB

此处的特殊字母选择反映出其目的在于使计数和引用索引的标签与 3rc 格式中的标签一样。

 
35ms [A=5] op {vC, vD, vE, vF, vG}, vtaboff@BBBB
[A=4] op {vC, vD, vE, vF}, vtaboff@BBBB
[A=3] op {vC, vD, vE}, vtaboff@BBBB
[A=2] op {vC, vD}, vtaboff@BBBB
[A=1] op {vC}, vtaboff@BBBB

此处的特殊字母选择反映出其目的在于使计数和引用索引的标签与 3rms 格式中的标签一样。

35c 格式的静态链接 invoke-virtualinvoke-super 指令的建议格式
35mi [A=5] op {vC, vD, vE, vF, vG}, inline@BBBB
[A=4] op {vC, vD, vE, vF}, inline@BBBB
[A=3] op {vC, vD, vE}, inline@BBBB
[A=2] op {vC, vD}, inline@BBBB
[A=1] op {vC}, inline@BBBB

此处的特殊字母选择反映出其目的在于使计数和引用索引的标签与 3rmi 格式中的标签一样。

35c 格式的内联链接 invoke-staticinvoke-virtual 指令的建议格式
AA|op BBBB CCCC 3rc op {vCCCC .. vNNNN}, meth@BBBB
op {vCCCC .. vNNNN}, site@BBBB
op {vCCCC .. vNNNN}, type@BBBB

其中 NNNN = CCCC+AA-1,即 A 确定计数 0..255C 确定第一个寄存器

 
3rms op {vCCCC .. vNNNN}, vtaboff@BBBB

其中 NNNN = CCCC+AA-1,即 A 确定计数 0..255C 确定第一个寄存器

3rc 格式的静态链接 invoke-virtualinvoke-super 指令的建议格式
3rmi op {vCCCC .. vNNNN}, inline@BBBB

其中 NNNN = CCCC+AA-1,即 A 确定计数 0..255C 确定第一个寄存器

3rc 格式的内联链接 invoke-staticinvoke-virtual 指令的建议格式
A|G|op BBBB F|E|D|C HHHH 45cc [A=5] op {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH
[A=4] op {vC, vD, vE, vF}, meth@BBBB, proto@HHHH
[A=3] op {vC, vD, vE}, meth@BBBB, proto@HHHH
[A=2] op {vC, vD}, meth@BBBB, proto@HHHH
[A=1] op {vC}, meth@BBBB, proto@HHHH
invoke-polymorphic
AA|op BBBB CCCC HHHH 4rcc op> {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH

其中 NNNN = CCCC+AA-1,即 A 确定计数 0..255C 确定第一个寄存器

invoke-polymorphic/range
AA|op BBBBlo BBBB BBBB BBBBhi 51l op vAA, #+BBBBBBBBBBBBBBBB const-wide