Dalvik-Bytecode-Format

Allgemeines Design

  • Das Maschinenmodell und die Aufrufkonventionen sollen ungefähr gängige reale Architekturen und C-ähnliche Aufrufkonventionen nachahmen:
    • Der Computer ist registerbasiert und Frames haben beim Erstellen eine feste Größe. Jeder Frame besteht aus einer bestimmten Anzahl von Registern (von der Methode angegeben) sowie allen zusätzlichen Daten, die zur Ausführung der Methode erforderlich sind, z. B. dem Programmzähler und einem Verweis auf die .dex-Datei, die die Methode enthält.
    • Bei Verwendung für Bitwerte (z. B. Ganzzahlen und Gleitkommazahlen) gelten Register als 32 Bit breit. Für 64‑Bit-Werte werden benachbarte Registerpaare verwendet. Für Registerpaare gibt es keine Ausrichtungsanforderungen.
    • Bei Verwendung für Objektverweise gelten Register als groß genug, um genau eine solche Referenz zu speichern.
    • Binärdarstellung: (Object) null == (int) 0.
    • Die N Argumente einer Methode landen nacheinander in den letzten N Registern des Aufrufframes der Methode. Breite Argumente belegen zwei Register. Instanzmethoden wird als erstes Argument eine this-Referenz übergeben.
  • Die Speichereinheit im Anweisungsstrom ist eine vorzeichenlose 16‑Bit-Quantität. Einige Bits in einigen Anweisungen werden ignoriert oder müssen null sein.
  • Anleitungen sind nicht grundlos auf einen bestimmten Typ beschränkt. Bei Anweisungen, die 32‑Bit-Registerwerte ohne Interpretation verschieben, muss beispielsweise nicht angegeben werden, ob Ganzzahlen oder Gleitkommazahlen verschoben werden.
  • Es gibt separate, aufgezählte und indexierte Konstantenpools für Verweise auf Strings, Typen, Felder und Methoden.
  • Bitweise Literaldaten werden inline im Anweisungsstream dargestellt.
  • Da in der Praxis für eine Methode in der Regel nicht mehr als 16 Register erforderlich sind und mehr als acht Register relativ häufig benötigt werden, sind viele Anweisungen auf die Adressierung der ersten 16 Register beschränkt. Soweit zumutbar, erlauben Anweisungen Verweise auf bis zu die ersten 256 Register. Außerdem gibt es Varianten einiger Anweisungen, die eine viel größere Anzahl von Registern zulassen, einschließlich zweier move-Anweisungen für alle Zwecke, die Register im Bereich v0v65535 adressieren können. Wenn keine Anweisungsvariante zur Adressierung eines gewünschten Registers verfügbar ist, wird der Inhalt des Registers vor dem Vorgang aus dem ursprünglichen Register in ein Low-Register und/oder nach dem Vorgang aus einem Low-Ergebnisregister in ein High-Register verschoben.
  • Es gibt mehrere „Pseudoanweisungen“, die zum Speichern von Datennutzlasten mit variabler Länge verwendet werden, auf die durch reguläre Anweisungen verwiesen wird (z. B. fill-array-data). Solche Anweisungen dürfen während des normalen Ablaufs der Ausführung niemals auftreten. Außerdem müssen sich die Anweisungen an geraden Bytecode-Offset-Positionen befinden, d. h. sie müssen auf 4-Byte-Grenze ausgerichtet sein. Um diese Anforderung zu erfüllen, müssen Tools zur DeX-Generierung eine zusätzliche nop-Anweisung als Spacer ausgeben, wenn eine solche Anweisung andernfalls nicht ausgerichtet wäre. Obwohl es nicht erforderlich ist, wird bei den meisten Tools davon ausgegangen, dass diese Anweisungen am Ende von Methoden ausgegeben werden, da andernfalls wahrscheinlich zusätzliche Anweisungen erforderlich wären, um um sie herum zu verzweigen.
  • Bei der Installation auf einem laufenden System werden einige Anweisungen möglicherweise geändert, um die statische Verknüpfung bei der Installation zu optimieren. So kann die Ausführung nach der Verknüpfung schneller erfolgen. Die vorgeschlagenen Varianten finden Sie im zugehörigen Dokument zu Anleitungsformaten. Das Wort „vorgeschlagen“ wird mit Bedacht verwendet. Die Implementierung dieser Empfehlungen ist nicht obligatorisch.
  • Syntax und Merkhilfen für Menschen:
    • Die Reihenfolge „Ziel dann Quelle“ für Argumente.
    • Einige Opcodes haben ein eindeutigen Namenssuffix, das den Typ angibt, auf den sie angewendet werden:
      • Typübergreifende 32‑Bit-Opcodes sind nicht gekennzeichnet.
      • Typübergreifende 64‑Bit-Opcodes haben das Suffix -wide.
      • Typspezifische Opcodes werden mit ihrem Typ (oder einer einfachen Abkürzung) abgeschlossen: -boolean, -byte, -char, -short, -int, -long, -float, -double, -object, -string, -class oder -void.
    • Einige Opcodes haben ein eindeutig identifizierendes Suffix, um ansonsten identische Vorgänge mit unterschiedlichen Anweisungslayouts oder Optionen zu unterscheiden. Diese Suffixe werden durch einen Schrägstrich („/“) von den Hauptnamen getrennt und dienen hauptsächlich dazu, eine Eins-zu-Eins-Zuordnung zu statischen Konstanten im Code zu ermöglichen, der ausführbare Dateien generiert und interpretiert, also Mehrdeutigkeiten für Menschen zu reduzieren.
    • In den Beschreibungen hier wird die Breite eines Werts (z.B. der Bereich einer Konstante oder die Anzahl der möglicherweise adressierten Register) durch die Verwendung eines Zeichens pro vier Bit Breite hervorgehoben.
    • Beispiel: In der Anleitung „move-wide/from16 vAA, vBBBB“:
      • move“ ist der Basis-Opcode, der den Basisvorgang angibt (Verschieben des Werts eines Registers).
      • wide“ ist das Namenssuffix, das angibt, dass mit großen (64‑Bit) Daten gearbeitet wird.
      • from16“ ist das Opcode-Suffix, das eine Variante mit einer 16‑Bit-Registerreferenz als Quelle angibt.
      • vAA“ ist das Zielregister (implizit durch den Vorgang; noch einmal: Zielargumente stehen immer zuerst), das sich im Bereich v0v255 befinden muss.
      • vBBBB“ ist das Quellregister, das sich im Bereich v0v65535 befinden muss.
  • Weitere Informationen zu den verschiedenen Befehlsformaten (unter „Op & Format“ aufgeführt) sowie zur Opcode-Syntax finden Sie im Dokument zu Befehlsformaten.
  • Weitere Informationen dazu, wo der Bytecode in das Gesamtbild passt, finden Sie im Dokument zum .dex-Dateiformat.

Zusammenfassung des Bytecode-Sets

Op & Format Tastenkombination / Syntax Argumente Beschreibung
00 10x nop   Abfallzyklen.

Hinweis:Datenhaltige Pseudoanweisungen sind mit diesem Opcode getaggt. In diesem Fall gibt das höchste Byte der Opcode-Einheit die Art der Daten an. Weitere Informationen finden Sie unten unter „packed-switch-payload-Format“, „sparse-switch-payload-Format“ und „fill-array-data-payload-Format“.

01 12x move vA, vB A: Zielregister (4 Bit)
B: Quellregister (4 Bit)
Verschieben Sie den Inhalt eines Nichtobjektregisters in ein anderes.
02 22x move/from16 vAA, vBBBB A: Zielregister (8 Bit)
B: Quellregister (16 Bit)
Verschieben Sie den Inhalt eines Nichtobjektregisters in ein anderes.
03 32x move/16 vAAAA, vBBBB A: Zielregister (16 Bit)
B: Quellregister (16 Bit)
Verschieben Sie den Inhalt eines Nichtobjektregisters in ein anderes.
04 12x move-wide vA, vB A: Zielregisterpaar (4 Bit)
B: Quellregisterpaar (4 Bit)
Verschieben Sie den Inhalt eines Registerpaars in ein anderes.

Hinweis:Es ist zulässig, von vN zu vN-1 oder vN+1 zu wechseln. Daher müssen bei Implementierungen beide Hälften eines Registerpaars gelesen werden, bevor etwas geschrieben wird.

05 22x move-wide/from16 vAA, vBBBB A: Zielregisterpaar (8 Bit)
B: Quellregisterpaar (16 Bit)
Verschieben Sie den Inhalt eines Registerpaars in ein anderes.

Hinweis:Die Implementierungsüberlegungen sind dieselben wie bei move-wide oben.

06 32x move-wide/16 vAAAA, vBBBB A: Zielregisterpaar (16 Bit)
B: Quellregisterpaar (16 Bit)
Verschieben Sie den Inhalt eines Registerpaars in ein anderes.

Hinweis:Die Implementierungsüberlegungen sind dieselben wie bei move-wide oben.

07 12x move-object vA, vB A: Zielregister (4 Bit)
B: Quellregister (4 Bit)
Verschieben des Inhalts eines Registers mit Objekten in ein anderes.
08 22x move-object/from16 vAA, vBBBB A: Zielregister (8 Bit)
B: Quellregister (16 Bit)
Verschieben des Inhalts eines Registers mit Objekten in ein anderes.
09 32x move-object/16 vAAAA, vBBBB A: Zielregister (16 Bit)
B: Quellregister (16 Bit)
Verschieben des Inhalts eines Registers mit Objekten in ein anderes.
0a 11x move-result vAA A: Zielregister (8 Bit) Verschieben Sie das einsilbige Nichtobjektergebnis der letzten invoke-kind in das angegebene Register. Dies muss als Anweisung unmittelbar nach einer invoke-kind erfolgen, deren (einwortiges, kein Objekt) Ergebnis nicht ignoriert werden soll. An anderer Stelle ist dies ungültig.
0b 11x move-result-wide vAA A:-Zielregisterpaar (8 Bit) Verschieben Sie das Doppelwortergebnis der letzten invoke-kind in das angegebene Registerpaar. Dies muss als Anweisung unmittelbar nach einer invoke-kind erfolgen, deren (Zweiwort-)Ergebnis nicht ignoriert werden soll. An anderer Stelle ist dies ungültig.
0c 11x move-result-object vAA A: Zielregister (8 Bit) Verschieben Sie das Objektergebnis des letzten invoke-kind in das angegebene Register. Dies muss als Anweisung unmittelbar nach einer invoke-kind oder filled-new-array erfolgen, deren (Objekt-)Ergebnis nicht ignoriert werden soll. An anderer Stelle ist dies ungültig.
0 Tage, 11-fach move-exception vAA A: Zielregister (8 Bit) Speichert eine gerade aufgetretene Ausnahme im angegebenen Register. Dies muss die erste Anweisung eines jeden Ausnahme-Handlers sein, dessen aufgefangene Ausnahme nicht ignoriert werden soll. Außerdem darf diese Anweisung nur als erste Anweisung eines Ausnahme-Handlers vorkommen. An anderer Stelle ist sie ungültig.
0e 10x return-void   Rückkehr aus einer void-Methode
0f 11x return vAA A:-Rückgabewertregister (8 Bit) Rückgabe von einer Methode mit einer einzelnen Breite (32 Bit), die keinen Objektwert zurückgibt.
10 11x return-wide vAA A: Rückgabewertregisterpaar (8 Bit) Rückgabe von einer Methode mit doppelter Breite (64 Bit), die einen Wert zurückgibt.
11 11x return-object vAA A:-Rückgabewertregister (8 Bit) Rückgabe aus einer Methode, die ein Objekt zurückgibt.
12 11n const/4 vA, #+B A: Zielregister (4 Bit)
B: signierte Ganzzahl (4 Bit)
Verschiebt den angegebenen Literalwert (auf 32 Bit erweitert) in das angegebene Register.
13 21 s const/16 vAA, #+BBBB A: Zielregister (8 Bit)
B: Ganzzahl mit Vorzeichen (16 Bit)
Verschiebt den angegebenen Literalwert (auf 32 Bit erweitert) in das angegebene Register.
14 31i const vAA, #+BBBBBBBB A: Zielregister (8 Bit)
B: beliebige 32‑Bit-Konstante
Verschiebt den angegebenen Literalwert in das angegebene Register.
15 21 Uhr const/high16 vAA, #+BBBB0000 A: Zielregister (8 Bit)
B: Ganzzahl mit Vorzeichen (16 Bit)
Verschiebt den angegebenen Literalwert (nach rechts auf 32 Bit erweitert) in das angegebene Register.
16 21 s const-wide/16 vAA, #+BBBB A: Zielregister (8 Bit)
B: Ganzzahl mit Vorzeichen (16 Bit)
Verschiebt den angegebenen Literalwert (auf 64 Bit erweitert mit Vorzeichen) in das angegebene Registerpaar.
17 31i const-wide/32 vAA, #+BBBBBBBB A: Zielregister (8 Bit)
B: Ganzzahl mit Vorzeichen (32 Bit)
Verschiebt den angegebenen Literalwert (auf 64 Bit erweitert mit Vorzeichen) in das angegebene Registerpaar.
18 51 l const-wide vAA, #+BBBBBBBBBBBBBBBB A: Zielregister (8 Bit)
B: beliebige Konstante mit doppelter Breite (64 Bit)
Verschiebt den angegebenen Literalwert in das angegebene Registerpaar.
19 21 Uhr const-wide/high16 vAA, #+BBBB000000000000 A: Zielregister (8 Bit)
B: Ganzzahl mit Vorzeichen (16 Bit)
Verschiebt den angegebenen Literalwert (nach rechts auf 64 Bit erweitert) in das angegebene Registerpaar.
1a 21c const-string vAA, string@BBBB A: Zielregister (8 Bit)
B: Stringindex
Verschiebt einen Verweis auf den String, der durch den angegebenen Index angegeben ist, in das angegebene Register.
1b 31c const-string/jumbo vAA, string@BBBBBBBB A: Zielregister (8 Bit)
B: Stringindex
Verschiebt einen Verweis auf den String, der durch den angegebenen Index angegeben ist, in das angegebene Register.
1c 21c const-class vAA, type@BBBB A:-Zielregister (8 Bit)
B:-Typindex
Verschiebt einen Verweis auf die durch den angegebenen Index angegebene Klasse in das angegebene Register. Wenn der angegebene Typ primitiv ist, wird ein Verweis auf die degenerierte Klasse des primitiven Typs gespeichert.
1d 11x monitor-enter vAA A: Referenzregister (8 Bit) Den Monitor für das angegebene Objekt erfassen.
1e 11x monitor-exit vAA A: Referenzregister (8 Bit) Monitor für das angegebene Objekt freigeben

Hinweis:Wenn diese Anweisung eine Ausnahme auslösen muss, muss dies so erfolgen, als wäre der PC bereits über die Anweisung hinausgekommen. Man kann sich das so vorstellen, dass die Anweisung (in gewissem Sinne) erfolgreich ausgeführt wird und die Ausnahme nach der Anweisung, aber bevor die nächste Anweisung ausgeführt werden kann, ausgelöst wird. Diese Definition ermöglicht es einer Methode, einen All-Catch-Monitor zur Bereinigung zu verwenden (z.B. finally)-Block als Monitorbereinigung für diesen Block selbst verwenden, um die beliebigen Ausnahmen zu behandeln, die aufgrund der bisherigen Implementierung von Thread.stop() auftreten können, und gleichzeitig für eine ordnungsgemäße Monitorhygiene zu sorgen.

1f 21c check-cast vAA, type@BBBB A: Referenzregister (8 Bit)
B: Typindex (16 Bit)
Eine ClassCastException wird geworfen, wenn die Referenz im angegebenen Register nicht in den angegebenen Typ umgewandelt werden kann.

Hinweis:Da A immer eine Referenz (und kein primitiver Wert) sein muss, schlägt dies bei Laufzeit fehl (d. h. es wird eine Ausnahme ausgelöst), wenn B auf einen primitiven Typ verweist.

20 22c instance-of vA, vB, type@CCCC A: Zielregister (4 Bit)
B: Referenzregister (4 Bit)
C: Typindex (16 Bit)
Speichern Sie im angegebenen Zielregister 1, wenn die angegebene Referenz eine Instanz des angegebenen Typs ist, oder 0, wenn nicht.

Hinweis:Da B immer eine Referenz (und kein primitiver Wert) sein muss, wird 0 immer gespeichert, wenn C auf einen primitiven Typ verweist.

21 12x array-length vA, vB A: Zielregister (4 Bit)
B: Register mit Arrayreferenz (4 Bit)
Speichert die Länge des angegebenen Arrays in Einträgen im angegebenen Zielregister.
22 21c new-instance vAA, type@BBBB A:-Zielregister (8 Bit)
B:-Typindex
Eine neue Instanz des angegebenen Typs erstellen und einen Verweis darauf im Ziel speichern. Der Typ muss sich auf eine Nicht-Array-Klasse beziehen.
23 22c new-array vA, vB, type@CCCC A: Zielregister (4 Bit)
B: Größeregister
C: Typindex
Erstellt ein neues Array mit dem angegebenen Typ und der angegebenen Größe. Der Typ muss ein Arraytyp sein.
24 35c filled-new-array {vC, vD, vE, vF, vG}, type@BBBB A: Arraygröße und Anzahl der Argumentwörter (4 Bit)
B: Typindex (16 Bit)
C..G: Argumentregister (jeweils 4 Bit)
Erstellt ein Array des angegebenen Typs und der angegebenen Größe und füllt es mit den angegebenen Inhalten. Der Typ muss ein Arraytyp sein. Der Inhalt des Arrays muss aus einem einzelnen Wort bestehen. Das heißt, es dürfen keine Arrays von long oder double verwendet werden, aber Referenztypen sind zulässig. Die erstellte Instanz wird als „Ergebnis“ gespeichert, genau wie die Anweisungen zur Methodenaufruf ihre Ergebnisse speichern. Daher muss die erstellte Instanz mit einer unmittelbar nachfolgenden move-result-object-Anweisung in ein Register verschoben werden, wenn sie verwendet werden soll.
25. 3. c filled-new-array/range {vCCCC .. vNNNN}, type@BBBB A: Arraygröße und Wortanzahl des Arguments (8 Bit)
B: Typindex (16 Bit)
C: Erstes Argumentregister (16 Bit)
N = A + C - 1
Erstellt ein Array des angegebenen Typs und der angegebenen Größe und füllt es mit dem angegebenen Inhalt. Erläuterungen und Einschränkungen entsprechen denen für filled-new-array, wie oben beschrieben.
26 31t fill-array-data vAA, +BBBBBBBB (mit ergänzenden Daten wie unten unter „fill-array-data-payload Format“ angegeben) A:-Arrayreferenz (8 Bit)
B: vorzeichenbehafteter „Branch“-Offset zu Pseudo-Anweisung für Tabellendaten (32 Bit)
Füllen Sie das angegebene Array mit den angegebenen Daten. Die Referenz muss auf ein Array von Primitiven verweisen. Die Datentabelle muss mit dem Typ übereinstimmen und darf nicht mehr Elemente enthalten, als in das Array passen. Das Array kann also größer als die Tabelle sein. In diesem Fall werden nur die ersten Elemente des Arrays festgelegt und der Rest bleibt unverändert.
27 11x vAA auswerfen A: Ausnahmeregister (8 Bit)
Die angegebene Ausnahme auslösen.
28 10t goto +AA A: Vorzeichenbehafteter Verzweigungsoffset (8 Bit) Unbedingt zur angegebenen Anweisung springen.

Hinweis:Der Verzweigungsoffset darf nicht 0 sein. Eine Schleife mit Verzweigung kann entweder mit goto/32 oder durch Einfügen eines nop als Ziel vor dem Verzweigungspunkt erstellt werden.

29 20t goto/16 +AAAA A: signed branch offset (16 Bit)
Unbedingt zur angegebenen Anweisung springen.

Hinweis:Der Verzweigungsoffset darf nicht 0 sein. Eine Schleife mit Verzweigung kann entweder mit goto/32 oder durch Einfügen eines nop als Ziel vor dem Verzweigungspunkt erstellt werden.

2a 30t goto/32 +AAAAAAAA A: Vorzeichenbehafteter Verzweigungsoffset (32 Bit)
Unbedingt zur angegebenen Anweisung springen.
2b 31t packed-switch vAA, +BBBBBBBB (mit ergänzenden Daten wie unten unter „packed-switch-payload Format“ angegeben) A:-Register zum Testen
B: vorzeichenbehafteter „Branch“-Offset zu Pseudo-Anweisung für Tabellendaten (32 Bit)
Springt basierend auf dem Wert im angegebenen Register mithilfe einer Tabelle mit Offsetwerten zu einer neuen Anweisung, die jedem Wert in einem bestimmten Ganzzahlbereich entspricht, oder geht zur nächsten Anweisung über, wenn keine Übereinstimmung gefunden wird.
2c 31t sparse-switch vAA, +BBBBBBBB (mit ergänzenden Daten wie unten unter „sparse-switch-payload Format“ angegeben) A:-Register zum Testen
B: vorzeichenbehafteter „Branch“-Offset zu Pseudo-Anweisung für Tabellendaten (32 Bit)
Springt je nach Wert im angegebenen Register mithilfe einer sortierten Tabelle von Wert-Offset-Paaren zu einer neuen Anweisung oder geht zur nächsten Anweisung über, wenn keine Übereinstimmung gefunden wird.
2d..31 23x cmpkind vAA, vBB, vCC
2d: cmpl-float (lt bias)
2e: cmpg-float (gt bias)
2f: cmpl-double (lt bias)
30: cmpg-double (gt bias)
31: cmp-long
A: Zielregister (8 Bit)
B: erstes Quellregister oder ‑paar
C: zweites Quellregister oder ‑paar
Führen Sie den angegebenen Vergleich mit Gleitkommazahlen oder long aus. Legen Sie a auf 0 fest, wenn b == c, auf 1, wenn b > c, oder auf -1, wenn b < c. Die für die Gleitkommaoperationen aufgeführte „Abweichung“ gibt an, wie NaN-Vergleiche behandelt werden: Anweisungen vom Typ „gt bias“ geben bei NaN-Vergleichen 1 zurück und Anweisungen vom Typ „lt bias“ geben -1 zurück.

Wenn Sie beispielsweise prüfen möchten, ob ein Gleitkommawert x < y ist, sollten Sie cmpg-float verwenden. Ein Ergebnis von -1 gibt an, dass der Test wahr war, und die anderen Werte geben an, dass er entweder aufgrund eines gültigen Vergleichs oder weil einer der Werte NaN war, falsch war.

32..37 22t if-test vA, vB, +CCCC
32: if-eq
33: if-ne
34: if-lt
35: if-ge
36: if-gt
37: if-le
A: erstes zu testendes Register (4 Bit)
B: zweites zu testendes Register (4 Bit)
C: vorzeichenbehafteter Verzweigungsoffset (16 Bit)
Springt zum angegebenen Ziel, wenn die Werte der beiden angegebenen Register den angegebenen Vergleichsbedingungen entsprechen.

Hinweis:Der Verzweigungsoffset darf nicht 0 sein. Eine Schleife mit Richtungswechsel kann entweder durch eine Verzweigung um eine rückwärtsgerichtete goto oder durch ein nop als Ziel vor der Verzweigung erstellt werden.

38..3d 21t if-testz vAA, +BBBB
38: if-eqz
39: if-nez
3a: if-ltz
3b: if-gez
3c: if-gtz
3d: if-lez
A:-Register zum Testen (8 Bit)
B: vorzeichenbehafteter Verzweigungsoffset (16 Bit)
Springt zum angegebenen Ziel, wenn der Wert des angegebenen Registers wie angegeben mit 0 verglichen wird.

Hinweis:Der Verzweigungsoffset darf nicht 0 sein. Eine Schleife mit Richtungswechsel kann entweder durch eine Verzweigung um eine rückwärtsgerichtete goto oder durch ein nop als Ziel vor der Verzweigung erstellt werden.

3e..43 10x (nicht verwendet)   (nicht verwendet)
44..51 23x arrayop vAA, vBB, vCC
44: aget
45: aget-wide
46: aget-object
47: aget-boolean
48: aget-byte
49: aget-char
4a: aget-short
4b: aput
4c: aput-wide
4d: aput-object
4e: aput-boolean
4f: aput-byte
50: aput-char
51: aput-short
A:-Wertregister oder ‑Paar; kann „Quelle“ oder „Ziel“ sein (8 Bit)
B:-Arrayregister (8 Bit)
C:-Indexregister (8 Bit)
Führen Sie den angegebenen Arrayvorgang am angegebenen Index des angegebenen Arrays aus und laden Sie ihn in das Wertregister.
52..5f 22c iinstanceop vA, vB, field@CCCC
52: iget
53: iget-wide
54: iget-object
55: iget-boolean
56: iget-byte
57: iget-char
58: iget-short
59: iput
5a: iput-wide
5b: iput-object
5c: iput-boolean
5d: iput-byte
5e: iput-char
5f: iput-short
A:-Wertregister oder ‑Paar; kann „Quelle“ oder „Ziel“ sein (4 Bit)
B:-Objektregister (4 Bit)
C:-Referenzindex des Instanzfelds (16 Bit)
Führen Sie den Feldvorgang für die identifizierte Objektinstanz mit dem entsprechenden Feld aus und laden Sie den Wert in das Wertregister.

Hinweis:Diese Opcodes sind geeignete Kandidaten für die statische Verknüpfung, wobei das Feldargument in einen direkteren Offset geändert wird.

60..6d 21c sstaticop vAA, field@BBBB
60: sget
61: sget-wide
62: sget-object
63: sget-boolean
64: sget-byte
65: sget-char
66: sget-short
67: sput
68: sput-wide
69: sput-object
6a: sput-boolean
6b: sput-byte
6c: sput-char
6d: sput-short
A:-Wertregister oder ‑Paar; kann „Quelle“ oder „Ziel“ sein (8 Bit)
B:-Index für den Verweis auf ein statisches Feld (16 Bit)
Führen Sie den Vorgang für das identifizierte statische Objektfeld mit dem identifizierten statischen Feld aus und laden Sie es in das Wertregister.

Hinweis:Diese Opcodes sind geeignete Kandidaten für die statische Verknüpfung, wobei das Feldargument in einen direkteren Offset geändert wird.

6e..72 35c invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB
6e: invoke-virtual
6f: invoke-super
70: invoke-direct
71: invoke-static
72: invoke-interface
A: Anzahl der Argumentwörter (4 Bit)
B: Methodenreferenzindex (16 Bit)
C..G: Argumentregister (jeweils 4 Bit)
Rufen Sie die angegebene Methode auf. Das Ergebnis (falls vorhanden) kann mit einer geeigneten move-result*-Variante als unmittelbar nachfolgende Anweisung gespeichert werden.

invoke-virtual wird verwendet, um eine normale virtuelle Methode aufzurufen, also eine Methode, die nicht static, private oder ein Konstruktor ist.

Wenn method_id auf eine Methode einer nicht-Schnittstellenklasse verweist, wird invoke-super verwendet, um die virtuelle Methode der übergeordneten Klasse aufzurufen (im Gegensatz zur Methode mit derselben method_id in der aufrufenden Klasse). Es gelten dieselben Methodeneinschränkungen wie für invoke-virtual.

Wenn sich method_id in Dex-Dateien der Version 037 oder höher auf eine Methodenoberfläche bezieht, wird invoke-super verwendet, um die spezifischeste, nicht überschriebene Version dieser Methode aufzurufen, die in dieser Schnittstelle definiert ist. Für die Methode gelten dieselben Einschränkungen wie für invoke-virtual. In Dex-Dateien vor Version 037 ist eine Schnittstelle vom Typ method_id unzulässig und nicht definiert.

invoke-direct wird verwendet, um eine nicht direkte static-Methode aufzurufen, d. h. eine Instanzmethode, die von Natur aus nicht überschrieben werden kann, also entweder eine private-Instanzmethode oder ein Konstruktor.

invoke-static wird verwendet, um eine static-Methode aufzurufen, die immer als direkte Methode betrachtet wird.

invoke-interface wird verwendet, um eine interface-Methode aufzurufen, d. h. auf ein Objekt, dessen konkrete Klasse nicht bekannt ist, mit einer method_id, die sich auf eine interface bezieht.

Hinweis:Diese Opcodes sind geeignete Kandidaten für die statische Verknüpfung, da das Methodenargument in einen direkteren Offset (oder ein Paar davon) geändert wird.

73 10x (nicht verwendet)   (nicht verwendet)
74..78 3rc invoke-kind/range {vCCCC .. vNNNN}, meth@BBBB
74: invoke-virtual/range
75: invoke-super/range
76: invoke-direct/range
77: invoke-static/range
78: invoke-interface/range
A: Argumentwortanzahl (8 Bit)
B: Methodenreferenzindex (16 Bit)
C: Erstes Argumentregister (16 Bit)
N = A + C - 1
Rufen Sie die angegebene Methode auf. Weitere Informationen, Hinweise und Vorschläge finden Sie in der ersten invoke-kind-Beschreibung oben.
79..7a 10x (nicht verwendet)   (nicht verwendet)
7b..8f 12x unop vA, vB
7b: neg-int
7c: not-int
7d: neg-long
7e: not-long
7f: neg-float
80: neg-double
81: int-to-long
82: int-to-float
83: int-to-double
84: long-to-int
85: long-to-float
86: long-to-double
87: float-to-int
88: float-to-long
89: float-to-double
8a: double-to-int
8b: double-to-long
8c: double-to-float
8d: int-to-byte
8e: int-to-char
8f: int-to-short
A: Zielregister oder ‑paar (4 Bit)
B: Quellregister oder ‑paar (4 Bit)
Führen Sie den identifizierten unary-Vorgang auf dem Quellregister aus und speichern Sie das Ergebnis im Zielregister.
90..af 23x binop vAA, vBB, vCC
90: add-int
91: sub-int
92: mul-int
93: div-int
94: rem-int
95: and-int
96: or-int
97: xor-int
98: shl-int
99: shr-int
9a: ushr-int
9b: add-long
9c: sub-long
9d: mul-long
9e: div-long
9f: rem-long
a0: and-long
a1: or-long
a2: xor-long
a3: shl-long
a4: shr-long
a5: ushr-long
a6: add-float
a7: sub-float
a8: mul-float
a9: div-float
aa: rem-float
ab: add-double
ac: sub-double
ad: mul-double
ae: div-double
af: rem-double
A: Zielregister oder ‑paar (8 Bit)
B: erstes Quellregister oder ‑paar (8 Bit)
C: zweites Quellregister oder ‑paar (8 Bit)
Führen Sie den identifizierten Binärvorgang auf den beiden Quellregistern aus und speichern Sie das Ergebnis im Zielregister.

Hinweis:Im Gegensatz zu anderen -long-Rechenoperationen (für die sowohl für die erste als auch für die zweite Quelle Registerpaare verwendet werden) verwenden shl-long, shr-long und ushr-long ein Registerpaar für die erste Quelle (den zu verschiebenden Wert) und ein einzelnes Register für die zweite Quelle (die Verschiebeweite).

b0..cf 12x binop/2addr vA, vB
b0: add-int/2addr
b1: sub-int/2addr
b2: mul-int/2addr
b3: div-int/2addr
b4: rem-int/2addr
b5: and-int/2addr
b6: or-int/2addr
b7: xor-int/2addr
b8: shl-int/2addr
b9: shr-int/2addr
ba: ushr-int/2addr
bb: add-long/2addr
bc: sub-long/2addr
bd: mul-long/2addr
be: div-long/2addr
bf: rem-long/2addr
c0: and-long/2addr
c1: or-long/2addr
c2: xor-long/2addr
c3: shl-long/2addr
c4: shr-long/2addr
c5: ushr-long/2addr
c6: add-float/2addr
c7: sub-float/2addr
c8: mul-float/2addr
c9: div-float/2addr
ca: rem-float/2addr
cb: add-double/2addr
cc: sub-double/2addr
cd: mul-double/2addr
ce: div-double/2addr
cf: rem-double/2addr
A: Ziel- und erstes Quellregister oder ‑paar (4 Bit)
B: zweites Quellregister oder ‑paar (4 Bit)
Führen Sie den identifizierten Binärvorgang auf den beiden Quellregistern aus und speichern Sie das Ergebnis im ersten Quellregister.

Hinweis:Im Gegensatz zu anderen -long/2addr-Arithmetikoperationen (für die sowohl für das Ziel/die erste Quelle als auch für die zweite Quelle Registerpaare verwendet werden) verwenden shl-long/2addr, shr-long/2addr und ushr-long/2addr ein Registerpaar für das Ziel/die erste Quelle (den zu verschiebenden Wert) und ein einzelnes Register für die zweite Quelle (die Verschiebeweite).

d0..d7 22s binop/lit16 vA, vB, #+CCCC
d0: add-int/lit16
d1: rsub-int (RSUB – umgekehrte Subtraktion)
d2: mul-int/lit16
d3: div-int/lit16
d4: rem-int/lit16
d5: and-int/lit16
d6: or-int/lit16
d7: xor-int/lit16
A: Zielregister (4 Bit)
B: Quellregister (4 Bit)
C: Vorzeichenbehaftete Ganzzahlkonstante (16 Bit)
Führt die angegebene binäre Operation auf dem angegebenen Register (erstes Argument) und dem Literalwert (zweites Argument) aus und speichert das Ergebnis im Zielregister.

Hinweis:rsub-int hat kein Suffix, da diese Version der Haupt-Opcode ihrer Familie ist. Weitere Informationen zur Semantik finden Sie unten.

d8..e2 22b binop/lit8 vAA, vBB, #+CC
d8: add-int/lit8
d9: rsub-int/lit8
da: mul-int/lit8
db: div-int/lit8
dc: rem-int/lit8
dd: and-int/lit8
de: or-int/lit8
df: xor-int/lit8
e0: shl-int/lit8
e1: shr-int/lit8
e2: ushr-int/lit8
A: Zielregister (8 Bit)
B: Quellregister (8 Bit)
C: Ganzzahlkonstante mit Vorzeichen (8 Bit)
Führt die angegebene binäre Operation auf dem angegebenen Register (erstes Argument) und dem Literalwert (zweites Argument) aus und speichert das Ergebnis im Zielregister.

Hinweis:Weitere Informationen zur Semantik von rsub-int finden Sie unten.

e3..f9 10x (nicht verwendet)   (nicht verwendet)
fa 45 cm³ invoke-polymorphic {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH A: Argumentwortanzahl (4 Bit)
B: Methodenreferenzindex (16 Bit)
C: Empfänger (4 Bit)
D..G: Argumentregister (jeweils 4 Bit)
H: Prototypreferenzindex (16 Bit)
Rufen Sie die angegebene polymorphe Methode auf. Das Ergebnis (falls vorhanden) kann mit einer geeigneten move-result*-Variante als unmittelbar nachfolgende Anweisung gespeichert werden.

Die Methodenreferenz muss auf eine signaturpolymorphe Methode verweisen, z. B. java.lang.invoke.MethodHandle.invoke oder java.lang.invoke.MethodHandle.invokeExact.

Der Empfänger muss ein Objekt sein, das die aufgerufene signaturpolymorphe Methode unterstützt.

In der Prototypreferenz werden die angegebenen Argumenttypen und der erwartete Rückgabetyp beschrieben.

Der invoke-polymorphic-Bytecode kann bei der Ausführung Ausnahmen auslösen. Die Ausnahmen werden in der API-Dokumentation für die aufgerufene signaturpolymorphe Methode beschrieben.

In Dex-Dateien ab Version 038 vorhanden.
fb 4rcc invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH A: Anzahl der Argumentwörter (8 Bit)
B: Methodenreferenzindex (16 Bit)
C: Empfänger (16 Bit)
H: Prototypreferenzindex (16 Bit)
N = A + C - 1
Rufen Sie den angegebenen Methoden-Handle auf. Weitere Informationen finden Sie in der Beschreibung von invoke-polymorphic oben.

In Dex-Dateien ab Version 038 vorhanden.
fc 35c invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB A: Anzahl der Argumentwörter (4 Bit)
B: Index der Verweisstelle des Aufrufs (16 Bit)
C..G: Argumentregister (jeweils 4 Bit)
Die angegebene Aufruf-Website wird aufgelöst und aufgerufen. Das Ergebnis des Aufrufs (falls vorhanden) kann mit einer geeigneten move-result*-Variante als unmittelbar nachfolgende Anweisung gespeichert werden.

Diese Anweisung wird in zwei Phasen ausgeführt: Aufrufswebsite-Auflösung und Aufrufswebsite-Aufruf.

Bei der Auflösung der Anruf-Website wird geprüft, ob der angegebenen Anruf-Website eine java.lang.invoke.CallSite-Instanz zugeordnet ist. Andernfalls wird die Bootstrap-Linker-Methode für die angegebene Aufrufstelle mit Argumenten aufgerufen, die in der DEX-Datei vorhanden sind (siehe call_site_item). Die Bootstrap-Linker-Methode gibt eine java.lang.invoke.CallSite-Instanz zurück, die dann der angegebenen Aufrufstelle zugeordnet wird, falls keine Verknüpfung vorhanden ist. Möglicherweise hat ein anderer Thread die Verknüpfung bereits hergestellt. In diesem Fall wird die Ausführung der Anweisung mit der ersten verknüpften java.lang.invoke.CallSite-Instanz fortgesetzt.

Der Aufruf der Aufrufstelle erfolgt auf dem java.lang.invoke.MethodHandle-Ziel der aufgelösten java.lang.invoke.CallSite-Instanz. Das Ziel wird aufgerufen, als würde invoke-polymorphic (siehe oben) mit dem Methoden-Handle und den Argumenten für die invoke-custom-Anweisung als Argumente für eine genaue Methoden-Handle-Aufruf ausgeführt.

Ausnahmen, die von der Bootstrap-Linker-Methode ausgelöst werden, werden in einen java.lang.BootstrapMethodError eingekapselt. Eine BootstrapMethodError wird auch in folgenden Fällen ausgelöst:
  • Die Bootstrap-Linker-Methode gibt keine java.lang.invoke.CallSite-Instanz zurück.
  • die zurückgegebene java.lang.invoke.CallSite ein null-Methoden-Handle-Ziel hat.
  • Das Ziel des Methoden-Handles ist nicht vom angeforderten Typ.
In Dex-Dateien ab Version 038 vorhanden.
fd 3rc invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB A: Anzahl der Argumentwörter (8 Bit)
B: Referenzindex der Aufrufstelle (16 Bit)
C: Register für das erste Argument (16 Bit)
N = A + C - 1
Eine Aufruf-Website auflösen und aufrufen. Weitere Informationen finden Sie in der Beschreibung von invoke-custom oben.

In Dex-Dateien ab Version 038 vorhanden.
fe 21c const-method-handle vAA, method_handle@BBBB A: Zielregister (8 Bit)
B: Methode-Handle-Index (16 Bit)
Verschieben Sie einen Verweis auf den Methoden-Handle, der durch den angegebenen Index angegeben ist, in das angegebene Register.

In Dex-Dateien ab Version 039 vorhanden.
ff 21c const-method-type vAA, proto@BBBB A: Zielregister (8 Bit)
B: Referenz zum Methodenprototyp (16 Bit)
Verschiebt einen Verweis auf den Methodeprototyp, der durch den angegebenen Index angegeben ist, in das angegebene Register.

In Dex-Dateien ab Version 039 vorhanden.

packed-switch-payload-Format

Name Format Beschreibung
ident ushort = 0x0100 Pseudo-Opcode identifizieren
Größe ushort Anzahl der Einträge in der Tabelle
first_key int Erster (und niedrigster) Switch-Case-Wert
Ziele int[] Liste mit size relativen Verzweigungszielen. Die Ziele beziehen sich auf die Adresse des Switch-Opcodes, nicht auf diese Tabelle.

Hinweis:Die Gesamtzahl der Code-Einheiten für eine Instanz dieser Tabelle beträgt (size * 2) + 4.

Sparse-Switch-Nutzlastformat

Name Format Beschreibung
ident ushort = 0x0200 Pseudo-Opcode identifizieren
Größe ushort Anzahl der Einträge in der Tabelle
Schlüssel int[] Liste der size-Schlüsselwerte, absteigend sortiert
Ziele int[] Liste von size relativen Verzweigungszielen, die jeweils dem Schlüsselwert am selben Index entsprechen. Die Ziele beziehen sich auf die Adresse des Switch-Opcodes, nicht auf diese Tabelle.

Hinweis:Die Gesamtzahl der Code-Einheiten für eine Instanz dieser Tabelle beträgt (size * 4) + 2.

fill-array-data-payload-Format

Name Format Beschreibung
ident ushort = 0x0300 Pseudo-Opcode identifizieren
element_width ushort Anzahl der Byte in jedem Element
Größe uint Anzahl der Elemente in der Tabelle
Daten ubyte[] Datenwerte

Hinweis:Die Gesamtzahl der Code-Einheiten für eine Instanz dieser Tabelle beträgt (size * element_width + 1) / 2 + 4.

Details zur mathematischen Operation

Hinweis:Gleitkommaoperationen müssen den IEEE 754-Regeln entsprechen und mit der Rundung auf den nächsten Wert und dem graduellen Unterlauf arbeiten, sofern nicht anders angegeben.

Opcode C-Semantik Hinweise
neg-int int32 a;
int32 result = -a;
Einäres Zweierkomplement.
not-int int32 a;
int32 result = ~a;
Einäres Eins-Komplement.
neg-long int64 a;
int64 result = -a;
Einer-Komplementarzeichenfolge.
not-long int64 a;
int64 result = ~a;
Einäres Eins-Komplement.
neg-float float a;
float result = -a;
Gleitkommanegation.
neg-double double a;
double result = -a;
Gleitkommanegation.
int-to-long int32 a;
int64 result = (int64) a;
Signaturerweiterung von int32 in int64.
int-to-float int32 a;
float result = (float) a;
Umwandlung von int32 in float mit Aufrundung auf die nächste ganze Zahl Dadurch geht bei einigen Werten die Genauigkeit verloren.
int-to-double int32 a;
double result = (double) a;
Umwandlung von int32 in double.
long-to-int int64 a;
int32 result = (int32) a;
Kürzung von int64 auf int32
long-to-float int64 a;
float result = (float) a;
Umwandlung von int64 in float mit Aufrundung auf die nächste ganze Zahl Dadurch geht bei einigen Werten die Genauigkeit verloren.
long-to-double int64 a;
double result = (double) a;
Umwandlung von int64 in double mit Aufrundung auf die nächste ganze Zahl Dadurch geht bei einigen Werten die Genauigkeit verloren.
float-to-int float a;
int32 result = (int32) a;
Umwandlung von float in int32 mit der Methode „auf Null aufrunden“. NaN und -0.0 (negative Null) werden in die Ganzzahl 0 umgewandelt. Unendliche Werte und Werte mit zu großer Größe, um dargestellt zu werden, werden je nach Vorzeichen in 0x7fffffff oder -0x80000000 umgewandelt.
float-to-long float a;
int64 result = (int64) a;
Umwandlung von float in int64 mit der Methode „auf Null aufrunden“. Hier gelten dieselben Sonderfallregeln wie für float-to-int, mit der Ausnahme, dass Werte außerhalb des zulässigen Bereichs je nach Vorzeichen in 0x7fffffffffffffff oder -0x8000000000000000 umgewandelt werden.
float-to-double float a;
double result = (double) a;
Umwandlung von float in double, wobei der Wert genau beibehalten wird.
double-to-int double a;
int32 result = (int32) a;
Umwandlung von double in int32 mit der Methode „auf Null aufrunden“. Hier gelten dieselben Sonderfallregeln wie für float-to-int.
double-to-long double a;
int64 result = (int64) a;
Umwandlung von double in int64 mit der Methode „auf Null aufrunden“. Hier gelten dieselben Sonderfallregeln wie für float-to-long.
double-to-float double a;
float result = (float) a;
Umwandlung von double in float mit Aufrundung auf die nächste ganze Zahl Dadurch geht bei einigen Werten die Genauigkeit verloren.
int-to-byte int32 a;
int32 result = (a << 24) >> 24;
Kürzung von int32 auf int8, Zeichen, das das Ergebnis erweitert.
int-to-char int32 a;
int32 result = a & 0xffff;
Kürzung von int32 auf uint16 ohne Vorzeichenerweiterung.
int-to-short int32 a;
int32 result = (a << 16) >> 16;
Kürzung von int32 auf int16, Zeichen, das das Ergebnis erweitert.
add-int int32 a, b;
int32 result = a + b;
Addition im Zweierkomplementarformat.
sub-int int32 a, b;
int32 result = a - b;
Subtraktion im Zweierkomplementarformat.
rsub-int int32 a, b;
int32 result = b - a;
Inverser Subtraktionsvorgang im Zweierkomplementarformat.
mul-int int32 a, b;
int32 result = a * b;
Multiplikation im Zweierkomplementarformat
div-int int32 a, b;
int32 result = a / b;
Division im Zweierkomplementarformat, auf null abgerundet (d. h. auf Ganzzahl gekürzt). Dies führt zu ArithmeticException, wenn b == 0.
rem-int int32 a, b;
int32 result = a % b;
Der Rest nach der Division im Zweierkomplementarformat. Das Vorzeichen des Ergebnisses ist mit dem von a identisch und wird genauer als result == a - (a / b) * b definiert. Dies führt zu ArithmeticException, wenn b == 0.
and-int int32 a, b;
int32 result = a & b;
Bitweises AND.
or-int int32 a, b;
int32 result = a | b;
Bitweises OR.
xor-int int32 a, b;
int32 result = a ^ b;
Bitweises XOR.
shl-int int32 a, b;
int32 result = a << (b & 0x1f);
Bitweise Linksverschiebung (mit maskiertem Argument).
shr-int int32 a, b;
int32 result = a >> (b & 0x1f);
Bitweise Rechtsverschiebung mit Signatur (mit maskiertem Argument).
ushr-int uint32 a, b;
int32 result = a >> (b & 0x1f);
Bitweise Rechtsverschiebung ohne Vorzeichen (mit maskiertem Argument).
add-long int64 a, b;
int64 result = a + b;
Addition im Zweierkomplementarformat.
sub-long int64 a, b;
int64 result = a - b;
Subtraktion im Zweierkomplementarformat.
mul-long int64 a, b;
int64 result = a * b;
Multiplikation im Zweierkomplementarformat
div-long int64 a, b;
int64 result = a / b;
Division im Zweierkomplementarformat, auf null abgerundet (d. h. auf Ganzzahl gekürzt). Dies führt zu ArithmeticException, wenn b == 0.
rem-long int64 a, b;
int64 result = a % b;
Rest nach Division im Zweierkomplementarformat. Das Vorzeichen des Ergebnisses ist mit dem von a identisch und wird genauer als result == a - (a / b) * b definiert. Dies führt zu ArithmeticException, wenn b == 0.
and-long int64 a, b;
int64 result = a & b;
Bitweises AND.
or-long int64 a, b;
int64 result = a | b;
Bitweises OR.
xor-long int64 a, b;
int64 result = a ^ b;
Bitweises XOR.
shl-long int64 a;
int32 b;
int64 result = a << (b & 0x3f);
Bitweise Linksverschiebung (mit maskiertem Argument).
shr-long int64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Bitweise Rechtsverschiebung mit Signatur (mit maskiertem Argument).
ushr-long uint64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Bitweise Rechtsverschiebung ohne Vorzeichen (mit maskiertem Argument).
add-float float a, b;
float result = a + b;
Gleitkommaaddition
sub-float float a, b;
float result = a - b;
Gleitkommasubtraktion.
mul-float float a, b;
float result = a * b;
Gleitkommamultiplikation.
div-float float a, b;
float result = a / b;
Gleitkommadivision.
rem-float float a, b;
float result = a % b;
Der Rest nach der Division im Gleitkommaformat. Diese Funktion unterscheidet sich vom IEEE 754-Rest und ist als result == a - roundTowardZero(a / b) * b definiert.
add-double double a, b;
double result = a + b;
Gleitkommaaddition
Unterdoppelbett double a, b;
double result = a - b;
Gleitkommasubtraktion.
mul-double double a, b;
double result = a * b;
Gleitkommamultiplikation.
div-double double a, b;
double result = a / b;
Gleitkommadivision.
rem-double double a, b;
double result = a % b;
Der Rest nach der Division im Gleitkommaformat. Diese Funktion unterscheidet sich vom IEEE 754-Rest und ist als result == a - roundTowardZero(a / b) * b definiert.