The insns of a code_item
are Dalvik bytecode. This page follows the Android Open Source Project’s
Dalvik
bytecode and
instruction
formats pages.
Machine model
- The machine is register-based. Each method’s frame has a fixed number of 32-bit
registers (
registers_size), writtenv0,v1and so on. A 64-bit value (long,double) uses two adjacent registers, with no alignment needed. An object reference takes one register;nullis zero. - A method’s arguments arrive in its last
ins_sizeregisters, in order, withthisfirst for instance methods; wide arguments take two. - The instruction stream is a sequence of 16-bit code units. The low byte of an
instruction’s first unit is its opcode. Addresses and branch offsets are counted in
code units. (The specification does not state the base of an
if-*orgotooffset; for switch tables it says targets are relative to the switch opcode.) - Many instructions can only name registers
v0–v15orv0–v255; themoveforms reach up tov65535. - Operands are written destination first. Suffixes give the type
(
-wide,-object,-boolean…) and, after a slash, the format variant (/16,/range,/2addr,/lit8…).
Instruction formats
A format ID has three characters: the number of 16-bit code units, the most
registers it names (r for a range), and a letter for the extra data. A
fourth character, s or i, marks the suggested formats for
statically linked or inlined code. In the layouts, each letter is four bits, read
from high to low within each code unit; units are separated by spaces, |
separates fields, op is the 8-bit opcode and Ø marks bits
that must be zero.
| Letter | Bits | Extra data |
|---|---|---|
b | 8 | signed immediate |
c | 16 or 32 | constant-pool index |
f | 16 | interface constant (static linking only) |
h | 16 | signed high-order immediate: the high bits of a 32- or 64-bit value whose low bits are zero |
i | 32 | immediate (int or float) |
l | 64 | immediate (long or double) |
m | 16 | method constant (static linking only) |
n | 4 | signed immediate |
s | 16 | signed immediate |
t | 8, 16 or 32 | branch target |
x | 0 | none |
| Format | Layout | Syntax | Notes |
|---|---|---|---|
00x | — | — | Unused opcodes. |
10x | ØØ|op | op | |
12x | B|A|op | op vA, vB | |
11n | B|A|op | op vA, #+B | |
11x | AA|op | op vAA | |
10t | AA|op | op +AA | goto |
20t | ØØ|op AAAA | op +AAAA | goto/16 |
20bc | AA|op BBBB | op AA, kind@BBBB | Suggested only: a verification error found ahead of time; A is the error type, B an index into a table of that kind. |
22x | AA|op BBBB | op vAA, vBBBB | |
21t | AA|op BBBB | op vAA, +BBBB | |
21s | AA|op BBBB | op vAA, #+BBBB | |
21h | AA|op BBBB | op vAA, #+BBBB0000 or #+BBBB000000000000 | |
21c | AA|op BBBB | op vAA, kind@BBBB | kind is string, type, field, method_handle or proto. |
23x | AA|op CC|BB | op vAA, vBB, vCC | |
22b | AA|op CC|BB | op vAA, vBB, #+CC | |
22t | B|A|op CCCC | op vA, vB, +CCCC | |
22s | B|A|op CCCC | op vA, vB, #+CCCC | |
22c | B|A|op CCCC | op vA, vB, kind@CCCC | kind is type or field. |
22cs | B|A|op CCCC | op vA, vB, fieldoff@CCCC | Suggested only: statically linked field access. |
30t | ØØ|op AAAAlo AAAAhi | op +AAAAAAAA | goto/32 |
32x | ØØ|op AAAA BBBB | op vAAAA, vBBBB | |
31i | AA|op BBBBlo BBBBhi | op vAA, #+BBBBBBBB | |
31t | AA|op BBBBlo BBBBhi | op vAA, +BBBBBBBB | |
31c | AA|op BBBBlo BBBBhi | op vAA, string@BBBBBBBB | const-string/jumbo |
35c | A|G|op BBBB F|E|D|C | op {vC, vD, vE, vF, vG}, kind@BBBB | A (0–5) is the number of argument registers, taken in the order C, D, E, F, G. kind is meth, call_site or type. |
35ms | A|G|op BBBB F|E|D|C | op {vC…vG}, vtaboff@BBBB | Suggested only. |
35mi | A|G|op BBBB F|E|D|C | op {vC…vG}, inline@BBBB | Suggested only. |
3rc | AA|op BBBB CCCC | op {vCCCC .. vNNNN}, kind@BBBB | AA registers starting at CCCC; NNNN = CCCC + AA − 1. |
3rms | AA|op BBBB CCCC | op {vCCCC .. vNNNN}, vtaboff@BBBB | Suggested only. |
3rmi | AA|op BBBB CCCC | op {vCCCC .. vNNNN}, inline@BBBB | Suggested only. |
45cc | A|G|op BBBB F|E|D|C HHHH | op {vC…vG}, meth@BBBB, proto@HHHH | invoke-polymorphic |
4rcc | AA|op BBBB CCCC HHHH | op {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH | invoke-polymorphic/range |
51l | AA|op BBBBlo BBBB BBBB BBBBhi | op vAA, #+BBBBBBBBBBBBBBBB | const-wide |
In the 30t, 31x and 51l layouts the first code unit after the opcode holds the low 16 bits (lo) and the last the high bits (hi). The suggested formats describe how a running system may rewrite instructions when it statically links them; implementing them is optional.
Opcodes
| Op | Format | Mnemonic | Meaning |
|---|---|---|---|
00 | 10x | nop | Nothing; also begins the data payloads. |
01 | 12x | move vA, vB | Copy a non-object register. |
02 | 22x | move/from16 vAA, vBBBB | The same, wider register numbers. |
03 | 32x | move/16 vAAAA, vBBBB | The same, 16-bit register numbers. |
04 | 12x | move-wide | Copy a register pair. |
05 | 22x | move-wide/from16 | |
06 | 32x | move-wide/16 | |
07 | 12x | move-object | Copy an object reference. |
08 | 22x | move-object/from16 | |
09 | 32x | move-object/16 | |
0A | 11x | move-result vAA | Single-word result of the preceding invoke. |
0B | 11x | move-result-wide | Double-word result of the preceding invoke. |
0C | 11x | move-result-object | Object result of the preceding invoke or filled-new-array. |
0D | 11x | move-exception | The caught exception; first instruction of a handler. |
0E | 10x | return-void | |
0F | 11x | return vAA | Return a 32-bit non-object value. |
10 | 11x | return-wide | Return a 64-bit value. |
11 | 11x | return-object | Return an object. |
12 | 11n | const/4 vA, #+B | 4-bit signed literal. |
13 | 21s | const/16 | 16-bit signed literal. |
14 | 31i | const | 32-bit literal. |
15 | 21h | const/high16 | Literal into the high 16 bits. |
16 | 21s | const-wide/16 | 16-bit literal, sign-extended to 64 bits. |
17 | 31i | const-wide/32 | 32-bit literal, sign-extended to 64 bits. |
18 | 51l | const-wide | 64-bit literal. |
19 | 21h | const-wide/high16 | Literal into the high 16 bits of a 64-bit value. |
1A | 21c | const-string vAA, string@BBBB | String reference. |
1B | 31c | const-string/jumbo | String reference, 32-bit index. |
1C | 21c | const-class vAA, type@BBBB | Class reference. |
1D | 11x | monitor-enter | Acquire an object’s monitor. |
1E | 11x | monitor-exit | Release it. |
1F | 21c | check-cast vAA, type@BBBB | Throw if the reference cannot be cast. |
20 | 22c | instance-of vA, vB, type@CCCC | 1 if vB is an instance of the type, else 0. |
21 | 12x | array-length | |
22 | 21c | new-instance vAA, type@BBBB | New object of a non-array class. |
23 | 22c | new-array vA, vB, type@CCCC | New array of size vB. |
24 | 35c | filled-new-array | New array filled from registers; result with move-result-object. |
25 | 3rc | filled-new-array/range | |
26 | 31t | fill-array-data vAA, +BBBBBBBB | Fill an array from a fill-array-data payload. |
27 | 11x | throw | |
28 | 10t | goto +AA | 8-bit offset, not 0. |
29 | 20t | goto/16 | 16-bit offset, not 0. |
2A | 30t | goto/32 | 32-bit offset; unlike the shorter forms it is not forbidden to be 0 (the specification suggests it for spin loops). |
2B | 31t | packed-switch vAA, +BBBBBBBB | Jump through a packed-switch payload. |
2C | 31t | sparse-switch | Jump through a sparse-switch payload. |
2D | 23x | cmpl-float | Compare: −1, 0 or 1; NaN gives −1. |
2E | 23x | cmpg-float | NaN gives 1. |
2F | 23x | cmpl-double | NaN gives −1. |
30 | 23x | cmpg-double | NaN gives 1. |
31 | 23x | cmp-long | |
32–37 | 22t | if-eq, if-ne, if-lt, if-ge, if-gt, if-le | Branch comparing vA with vB. |
38–3D | 21t | if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez | Branch comparing vAA with zero. |
3E–43 | 10x | unused | |
44–4A | 23x | aget, aget-wide, aget-object, aget-boolean, aget-byte, aget-char, aget-short | vAA = vBB[vCC]. |
4B–51 | 23x | aput, aput-wide, aput-object, aput-boolean, aput-byte, aput-char, aput-short | vBB[vCC] = vAA. |
52–58 | 22c | iget, iget-wide, iget-object, iget-boolean, iget-byte, iget-char, iget-short | vA = instance field of vB. |
59–5F | 22c | iput, iput-wide, iput-object, iput-boolean, iput-byte, iput-char, iput-short | Instance field of vB = vA. |
60–66 | 21c | sget, sget-wide, sget-object, sget-boolean, sget-byte, sget-char, sget-short | vAA = static field. |
67–6D | 21c | sput, sput-wide, sput-object, sput-boolean, sput-byte, sput-char, sput-short | Static field = vAA. |
6E | 35c | invoke-virtual | Call a virtual method. |
6F | 35c | invoke-super | Call the superclass’s version of a method. |
70 | 35c | invoke-direct | Call a private method or constructor. |
71 | 35c | invoke-static | |
72 | 35c | invoke-interface | |
73 | 10x | unused | |
74–78 | 3rc | invoke-virtual/range, invoke-super/range, invoke-direct/range, invoke-static/range, invoke-interface/range | The same with a register range. |
79–7A | 10x | unused | |
7B–8F | 12x | neg-int, not-int, neg-long, not-long, neg-float, neg-double, int-to-long, int-to-float, int-to-double, long-to-int, long-to-float, long-to-double, float-to-int, float-to-long, float-to-double, double-to-int, double-to-long, double-to-float, int-to-byte, int-to-char, int-to-short | Unary operations and conversions, vA = op vB, in that order from 7B. |
90–AF | 23x | add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, xor-int, shl-int, shr-int, ushr-int, add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, xor-long, shl-long, shr-long, ushr-long, add-float, sub-float, mul-float, div-float, rem-float, add-double, sub-double, mul-double, div-double, rem-double | vAA = vBB op vCC, in that order from 90. Integer division and remainder by zero throw an exception; shift distances are masked to 5 bits (int) or 6 bits (long). |
B0–CF | 12x | the same 32 operations with /2addr: add-int/2addr … rem-double/2addr | vA = vA op vB, in the same order from B0. |
D0–D7 | 22s | add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 | vA = vB op literal; rsub-int is literal − vB. |
D8–E2 | 22b | add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, shl-int/lit8, shr-int/lit8, ushr-int/lit8 | vAA = vBB op literal. |
E3–F9 | 10x | unused | |
FA | 45cc | invoke-polymorphic | Call a signature-polymorphic method (038). |
FB | 4rcc | invoke-polymorphic/range | (038) |
FC | 35c | invoke-custom | Resolve and call a call site, call_site@BBBB (038). |
FD | 3rc | invoke-custom/range | (038) |
FE | 21c | const-method-handle | Method handle reference (039). |
FF | 21c | const-method-type | Method prototype reference (039). |
Data payloads
Switch tables and array data sit in the instruction stream as pseudo-instructions,
usually at the end of the method. Each starts at a 4-byte-aligned address (a
nop pads if needed), and its first code unit is an identifier whose low
byte is 00, the nop opcode. They are never executed.
packed-switch-payload
| Type and name | Meaning |
|---|---|
ushort ident | 0x0100 |
ushort size | Number of entries. |
int first_key | The first, lowest case value. |
int targets[size] | Branch targets for first_key, first_key + 1 and so on, relative to the switch instruction. |
Length: size × 2 + 4 code units.
sparse-switch-payload
| Type and name | Meaning |
|---|---|
ushort ident | 0x0200 |
ushort size | Number of entries. |
int keys[size] | Case values, sorted from low to high. |
int targets[size] | Branch target for each key, relative to the switch instruction. |
Length: size × 4 + 2 code units.
fill-array-data-payload
| Type and name | Meaning |
|---|---|
ushort ident | 0x0300 |
ushort element_width | Bytes per element. |
uint size | Number of elements. |
ubyte data[] | The element values, little-endian. |
Length: (size × element_width + 1) / 2 + 4 code units.
Example
12 01 const/4 v1, #+0 (B=0, A=1, op 12)
1A 00 05 00 const-string v0, string@0005
6E 20 03 00 10 00
invoke-virtual {v0, v1}, meth@0003 (A=2, G=0; C=0, D=1)
0E 00 return-void
Bytes are as stored: each code unit is a little-endian ushort, so its
low byte (the opcode) comes first.
Sources
- Dalvik bytecode – general design, the summary of the bytecode set (every opcode, format and meaning) and the payload formats
- Dalvik executable instruction formats – the format IDs, letters, layouts and syntax
- Dalvik executable format –
code_itemand the little-endianushortinstruction array