参考资料
https://source.android.com/devices/tech/dalvik/dalvik-bytecode.html
https://source.android.com/devices/tech/dalvik/instruction-formats.html
http://www.milk.com/kodebase/dalvik-docs-mirror/docs/dalvik-bytecode.html
什么是Dalvik字节码?
- const 指令:负责将常量值放入到虚拟寄存器中;
- mov指令:在虚拟寄存器之间拷贝数据;
- 比较指令:比较两个寄存器的值,有部分指令是直接与0比较的;
- 分支指令:包括if系列指令如if-eq, if-ge等等,以及switch指令,goto指令。switch指令作为一个单独指令存在的;
- invoke指令:函数调用指令,分成invoke-direct, invoke-static, invoke-native, invoke-virtual和invoke-interface几大系列;
- field操作指令:包括put/get,针对静态域和非静态域;
- class相关的指令:比如new-instance, instance-of,checkcast等等
- 异常处理指令:包括throw, move-exception这样的指令;
- 算术、位移等指令:不多说了;
- 其他指令
字节码的格式?
dalvik字节码是以一个字(两字节)为单位,必须是一个字的整数倍。所以,你看到dexdump出的字节指令,其长度都必须x2才能得到其字节长度。
不同指令的字节码长度不一样,相同操作类型的指令长度是一样的,根据指令操作类型,就可以确定指令的长度。比如 mov v1, v2,指令长度是1字。
字节码在dex文件中存储时,都是小端的。因此,第一个字节必须是操作类型(操作符),是一个0~255范围内的一个数字,根据操作符,我们可以确定后续有多少个字以及表示什么意思。
每个操作符都有一个格式(format),根据格式,我们可以知道该指令的长度,参数有哪些、每个参数的长度、参数是如何存储的,这些重要的信息。不同的指令可以有相同的格式,因此,dalvik将他们分类,并给每个格式以不同的描述。每种格式被称为Format ID。
下表详细说明了dalvik字节码的格式(来自https://source.android.com/devices/tech/dalvik/instruction-formats.html)。这个表分为4列。其中前3列分别是Format, ID, Syntax。
Format列
ID列
Mnemonic | Bit Sizes | Meaning |
---|---|---|
b | 8 | 有符号1字节立即数 |
c | 16, 32 | 常量池索引 |
f | 16 | interface相关的常量 |
h | 16 | 16位有符号立即数,表示32/64位中的最高16位 |
i | 32 | 32位有符号立即数,或者32位的浮点数 |
l | 64 | 64位有符号立即数,或者双精度浮点数 |
m | 16 | method的常量索引值 |
n | 4 | 4位有符号立即数 |
s | 16 | 16位有符号立即数 |
t | 8, 16, 32 | 分支目标偏移值 |
x | 0 | 无更多附加数 |
Syntax列
- "vX": 前缀"v"表示这是一个虚拟寄存器,"X"对应Foramt列中的参数,"X"的值就是虚拟寄存器的索引;