Morrison.J Android Dev Engineer

Dalvik可执行指令格式


本文记录了Dalvik Executable instruction formats详细阅读笔记,做大体翻译。

Introduction

本文列出Dalvik指令格式,用于描述Dalvik可执行格式和Dalvik字节码。 应当结合bytecode reference document一起使用。

按位描述(Bitwise descriptions)

Formats表中,第一列指明了格式的位布局。布局包含了__一个或者多个”words”__,”word”翻译为”字”,每一个”words”代表一个16-bit编码单元。 每一个word中的字符代表4个二进制位,从高位往低位读取,使用”|”分割以辅助阅读。从’A’开始的大写字母,用于表示格式中的段, 这个段由后面的语法列进行定义。”op”项用于表示格式中的eight-bit操作码。一个被削减过的0, 就是说0中间被砍了一刀的这样一个符号,用于表示指定位置中所有为0的位。

一般来说,一个编码单元使用有序的先低后高的字母序列表示。但是也有例外,主要是用于区别具有相同格式的编码指令。

例如,”B|A|op CCCC”: “B|A|op” 属于第一个”word”,”CCCC”属于第二个”word”,每一个word是一个16-bit code units(16-bit编码单元)。 第一个word包含低8位的操作码和一对高4位的value;第二个word代表了单个16位的值。也就是说,对于第一个word,低8位操作码是op,一对高4位的值分别是B和A,共16位。 这样,两个16位组合起来就是32位,所以,这条Dalvik指令等于32位二进制。

Format IDs(格式的IDs)

Formats表中,第二列指明了某种格式的ID,ID可以用于其它文件的参考,也可以在编码中识别格式的类型,一个id对应一种编码格式的意思。

大多数的id包含三个字符,两个十进制数和一个字母。第一个十进制数表示16-bit code units在表格中的个数,第二个十进制数用于表示当前格式包含的最大寄存器个数(某些指令可以动态调整寄存器的个数)。 特别的,标识符”r”正代表编码寄存器的个数范围。最后那个字母半自动地(semi-mnemonically)表示了格式中任何其它附加的类型。 比如”21t”表示,指令是2个word(两个16-bit编码单元),使用一个寄存器,包含brach target(转移目标)。

Mnemonic 助记符 Bit Sizes Meaning
b 8 immediate signed byte 8位立即数
c 16, 32 constant pool index 常量池索引
f 16 interface constants (only used in statically linked formats) 接口常量(只使用于静态链接格式)
h 16 immediate signed hat (high-order bits of a 32- or 64-bit value; low-order bits are all 0) 立即有符号数,高位有效
i 32 immediate signed int, or 32-bit float 立即有符号整数或者32位浮点数
l 64 immediate signed long, or 64-bit double 立即有符号长整数或者64位双精度浮点数
m 16 method constants (only used in statically linked formats) 方法常量
n 4 immediate signed nibble 立即有符号半字节数
s 16 immediate signed short 立即有符号短整型
t 8, 16, 32 branch target 转移目标(跳转)
x 0 no additional data 没有附加的信息

Syntax 语法

下表中第三列使用人类可识别的语法表示前面指定的格式,op在前面,然后跟随参数,所有内容以逗号分隔。

所有在第一列中指定的参数都将以原型出现,不加修改。比如:BB还是BB。

表示寄存器时使用”vX”,而不是”rX”,因为v表示虚拟寄存器的意思,从而不会与Dalvik实体寄存器的”r”冲突。由此,我们可以简洁地同时描述虚拟寄存器和实体寄存器。

”#+X”表示高位非零。

“+X”表示相对地址。

形如 “kind@X”表示常量池中内容X。kind可以是”string” (string pool index), “type” (type pool index), “field” (field pool index), and “meth” (method pool index)。

类似于常量池的表示方式,vtable offsets (indicated as “vtaboff”) and field offsets (indicated as “fieldoff”)表示两种预链接偏移量。

当格式中的某个符号无法明确表示一个值的时候,采用类似”[X=N]” 的变体形式,比如”[A=2]”,以表示A在等于2的情况下指令的语法。

The formats表

请查阅官网 The formats.

例子

AA|op BBBB 20bc op AA, kind@BBBB suggested format for statically determined verification errors; A is the type of error and B is an index into a type-appropriate table (e.g. method references for a no-such-method error)
  • 格式:AA|op BBBB,AA是8bit的数,从ID可见它是一个8bit的立即数,op是操作码,BBBB是16bit的数,从ID可见它用于字符串常量池索引。
  • ID:20bc,2个word,0个寄存器,b表示8位立即数,c表示常量池索引。
  • 语法:op AA, kind@BBBB,应当写成这样的供人类阅读的语法。
  • 描述:建议这样的格式用于错误处理,AA作为错误码,BBBB用于索引常量池中的错误类型信息(比如说,常量池中存放:没有这个函数,那么BBBB就是这个字符串的偏移量)。

问:BBBB是字符串对于文件的偏移地址还是对于常量池的偏移量? 答:是对于常量池的偏移量,否则kind就不需要分类了,实践证明的确是常量池的偏移量。


Similar Posts

下一篇 Dalvik-bytecode

Comments