Dalvik指令概述

作者 Known Rabbit 日期 2017-03-17
Dalvik指令概述

书里写的实在是太差了。自己稍微总结一下。

字节码表示方式 Bytecode

位描述 Bitwise description

用于表示指令二进制码的数据布局。

[A|G|op BBBB F|E|D|C]
  • 一个字母代表4bit数据(一发十六进制)

  • op表示8bit操作码(一个字节byte,两发十六进制)

  • Ø表示指令中此位必须为零

  • 每16位一个空格(一个字word)

  • 竖线分隔不同的数据

指令格式标识 Format IDs

用于表示指令的长度、参数类型。

N N a [s/i]

额外数据类型:

语法

用位描述和格式标示定义的,给人看的(human-oriented)指令语法。

op vAA, string@BBBB
  • 逗号分隔参数

  • 指令类型 op 为第一个word的low byte。高八位可以为参数,可以为空

  • vX 为寄存器,几个X就是寄存器标号(地址)大小

  • #+X 常量

  • +X 为相对(当前指令)的地址偏移量

  • @X 为常量池索引。 kind=[string, type, field, meth, site] site=call site

寄存器命名法

令函数foo()使用了M个寄存器,有N个参数。

指令列表

以下表格包含所有指令的列表。

原文:https://source.android.com/devices/tech/dalvik/dalvik-bytecode.html#instructions

以上表格的第一列的第二部分指令格式ID,对应的(给人看的)指令数据布局列表,见

原文:https://source.android.com/devices/tech/dalvik/instruction-formats.html#formats

第二个表格不用记,用的时候查表格就是了。

实现

  • dalvik.bytecode.Opcodes接口定义完整字节码列表。

    • 源码位于 libcore/dalvik/src/main/java/dalvik/bytecode/Opcodes.java

    • dalvik/opcode-gen/bytecode.txt 用于生成以上接口的指令集

    • kitkat版本及以下的安卓源码,可在dalvik/vm/mterp/c找到指令实现

    • lollipop及以上版本,可在 art/runtime/interpreter/mterp/[arch] 下找到对应指令实现(汇编)

以kitcat的 OP_MOVE.cpp 为例。

INST_A宏:获取指令高八位的低4位。

INST_B:获取高八位的高4位。

GET_REGISTER:存值

fp[]:栈帧寄存器,函数的局部变量区,存储所有寄存器值。其索引为寄存器编号。

FINISH:调整PC寄存器,移动至此条指令后。

底层架构

  • 部分寄存器映射到CPU寄存器,部分由调用栈模拟。

  • 寄存器全部为32位,64位数据由相邻两个寄存器表示。

  • 寄存器编号 v0-v65535,因为操作符为16位(v0000-vFFFF)

    • 大部分函数使用的寄存器少于16个,因此16以下的寄存器,编号小于1字节,对应特殊指令(速度更快?)
  • 寄存器个数在函数被调用、分配调用栈时预留对应空间,于函数头由 .register 指令指定。