Dalvik-Bytecode-Format

Allgemeines Design

  • Das Maschinenmodell und die Aufrufkonventionen sollen gängige reale Architekturen und Aufrufkonventionen im C-Stil annähernd imitieren:
    • Die Maschine ist registerbasiert und die Größe der Rahmen wird bei der Erstellung festgelegt. Jeder Frame besteht aus einer bestimmten Anzahl von Registern (durch die Methode angegeben) sowie allen Zusatzdaten, die zum Ausführen der Methode erforderlich sind, wie z. B. (aber nicht beschränkt auf) 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) werden Register als 32 Bit breit betrachtet. Für 64-Bit-Werte werden benachbarte Registerpaare verwendet. Es gibt keine Ausrichtungsanforderung für Registerpaare.
    • Bei der Verwendung für Objektreferenzen gelten Register als breit genug, um genau eine solche Referenz aufzunehmen.
    • In Bezug auf die bitweise Darstellung (Object) null == (int) 0 .
    • Die N Argumente einer Methode landen der Reihe nach in den letzten N Registern des Aufrufrahmens der Methode. Breite Argumente verbrauchen zwei Register. Instanzmethoden erhalten this Referenz als erstes Argument.
  • Die Speichereinheit im Befehlsstrom ist eine vorzeichenlose 16-Bit-Größe. Einige Bits in einigen Anweisungen werden ignoriert/müssen Null sein.
  • Anweisungen sind nicht unnötig auf einen bestimmten Typ beschränkt. Beispielsweise müssen Anweisungen, die 32-Bit-Registerwerte ohne Interpretation verschieben, nicht angeben, ob es sich um Ints oder Floats handelt.
  • Es gibt separat aufgezählte und indizierte Konstantenpools für Verweise auf Zeichenfolgen, Typen, Felder und Methoden.
  • Bitweise Literaldaten werden im Befehlsstrom inline dargestellt.
  • Da es in der Praxis selten vorkommt, dass eine Methode mehr als 16 Register benötigt, und da die Notwendigkeit von mehr als acht Registern durchaus üblich ist , beschränken sich viele Anweisungen darauf, nur die ersten 16 Register zu adressieren. Wenn dies vernünftigerweise möglich ist, erlauben Anweisungen Verweise auf bis zu den ersten 256 Registern. Darüber hinaus verfügen einige Befehle über Varianten, die eine viel größere Registeranzahl ermöglichen, einschließlich eines Paars von Catch-All- move , die Register im Bereich v0v65535 adressieren können. In Fällen, in denen eine Befehlsvariante nicht verfügbar ist, um ein gewünschtes Register anzusprechen, wird erwartet, dass der Registerinhalt vom ursprünglichen Register in ein niedriges Register (vor der Operation) und/oder von einem niedrigen Ergebnisregister in ein hohes verschoben wird registrieren (nach der Operation).
  • Es gibt mehrere „Pseudoanweisungen“, die zum Speichern von Datennutzlasten 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 Ausführungsablaufs niemals angetroffen werden. Darüber hinaus müssen sich die Anweisungen auf geraden Bytecode-Offsets befinden (d. h. 4-Byte-ausgerichtet). Um diese Anforderung zu erfüllen, müssen Dex-Generierungstools eine zusätzliche nop Anweisung als Abstandszeichen ausgeben, wenn eine solche Anweisung andernfalls nicht ausgerichtet wäre. Obwohl dies nicht erforderlich ist, wird erwartet, dass sich die meisten Tools schließlich dafür entscheiden, diese Anweisungen am Ende der Methoden auszugeben, da andernfalls wahrscheinlich zusätzliche Anweisungen erforderlich wären, um sie zu umgehen.
  • Bei der Installation auf einem laufenden System können einige Anweisungen geändert und ihr Format geändert werden, um die statische Verknüpfung während der Installation zu optimieren. Dies soll eine schnellere Ausführung ermöglichen, sobald die Verknüpfung bekannt ist. Die vorgeschlagenen Varianten finden Sie im zugehörigen Dokument zu den Anweisungsformaten . Das Wort „empfohlen“ wird mit Bedacht verwendet; es ist nicht zwingend erforderlich, diese umzusetzen.
  • Menschliche Syntax und Mnemonik:
    • Ziel-dann-Quelle-Reihenfolge für Argumente.
    • Einige Opcodes haben ein eindeutiges Namenssuffix, um den Typ bzw. die Typen anzugeben, mit denen sie arbeiten:
      • Typallgemeine 32-Bit-Opcodes sind nicht markiert.
      • Typallgemeine 64-Bit-Opcodes werden mit dem Suffix -wide versehen.
      • Typspezifischen Opcodes wird ihr Typ (oder eine einfache Abkürzung) angehängt, einer der folgenden: -boolean -byte -char -short -int -long -float -double -object -string -class -void .
    • Einige Opcodes verfügen über ein eindeutiges Suffix, um ansonsten identische Operationen mit unterschiedlichen Befehlslayouts oder Optionen zu unterscheiden. Diese Suffixe werden durch einen Schrägstrich („ / “) von den Hauptnamen getrennt und existieren hauptsächlich überhaupt, um eine Eins-zu-Eins-Zuordnung mit statischen Konstanten im Code zu ermöglichen, der ausführbare Dateien generiert und interpretiert (d. h. um Mehrdeutigkeiten zu reduzieren). für den Menschen).
    • In den Beschreibungen hier wird die Breite eines Werts (der beispielsweise den Bereich einer Konstante oder die Anzahl der möglicherweise adressierten Register angibt) durch die Verwendung eines Zeichens pro vier Bit Breite hervorgehoben.
    • Beispielsweise in der Anweisung „ move-wide/from16 vAA, vBBBB “:
      • move “ ist der Basis-Opcode, der die Basisoperation angibt (den Wert eines Registers verschieben).
      • wide “ ist das Namenssuffix, das darauf hinweist, dass es mit Wide-Daten (64 Bit) arbeitet.
      • from16 “ ist das Opcode-Suffix, das eine Variante angibt, die eine 16-Bit-Registerreferenz als Quelle hat.
      • vAA “ ist das Zielregister (durch die Operation impliziert; auch hier gilt die Regel, dass Zielargumente immer an erster Stelle stehen), das im Bereich v0v255 liegen muss.
      • vBBBB “ ist das Quellregister, das im Bereich v0v65535 liegen muss.
  • Weitere Informationen zu den verschiedenen Befehlsformaten (aufgelistet unter „Op & Format“) sowie Einzelheiten zur Opcode-Syntax finden Sie im Dokument „ Anweisungsformate“.
  • Weitere Informationen dazu, wo der Bytecode in das Gesamtbild passt, finden Sie im Dokument .dex Dateiformat .

Zusammenfassung des Bytecodesatzes

Betrieb und Format Mnemonik / Syntax Argumente Beschreibung
00 10x Nein Abfallkreisläufe.

Hinweis: Datentragende Pseudoanweisungen werden mit diesem Opcode gekennzeichnet. In diesem Fall gibt das höherwertige Byte der Opcode-Einheit die Art der Daten an. Siehe „ packed-switch-payload Format“, „ sparse-switch-payload Format“ und „ fill-array-data-payload Format“ unten.

01 12x bewegen vA, vB A: Zielregister (4 Bits)
B: Quellregister (4 Bits)
Verschieben Sie den Inhalt eines Nichtobjektregisters in ein anderes.
02 22x Umzug/von16 vAA, vBBBB A: Zielregister (8 Bit)
B: Quellregister (16 Bit)
Verschieben Sie den Inhalt eines Nichtobjektregisters in ein anderes.
03 32x Zug/16 vAAAA, vBBBB A: Zielregister (16 Bit)
B: Quellregister (16 Bit)
Verschieben Sie den Inhalt eines Nichtobjektregisters in ein anderes.
04 12x zugweit vA, vB A: Zielregisterpaar (4 Bits)
B: Quellregisterpaar (4 Bits)
Verschieben Sie den Inhalt eines Registerpaars in ein anderes.

Hinweis: Es ist zulässig, von v N zu v N-1 oder v N+1 zu wechseln, daher müssen Implementierungen dafür sorgen, dass beide Hälften eines Registerpaars gelesen werden, bevor etwas geschrieben wird.

05 22x zugweit/ab 16 vAA, vBBBB A: Zielregisterpaar (8 Bits)
B: Quellregisterpaar (16 Bit)
Verschieben Sie den Inhalt eines Registerpaars in ein anderes.

Hinweis: Die Überlegungen zur Implementierung sind die gleichen wie oben bei move-wide .

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

Hinweis: Die Überlegungen zur Implementierung sind die gleichen wie oben bei move-wide .

07 12x Objekt bewegen vA, vB A: Zielregister (4 Bits)
B: Quellregister (4 Bits)
Verschieben Sie den Inhalt eines objekttragenden Registers in ein anderes.
08 22x move-object/from16 vAA, vBBBB A: Zielregister (8 Bit)
B: Quellregister (16 Bit)
Verschieben Sie den Inhalt eines objekttragenden Registers in ein anderes.
09 32x Objekt bewegen/16 vAAAA, vBBBB A: Zielregister (16 Bit)
B: Quellregister (16 Bit)
Verschieben Sie den Inhalt eines objekttragenden Registers in ein anderes.
0a 11x Umzugsergebnis vAA A: Zielregister (8 Bit) Verschieben Sie das Einzelwort-Nicht-Objekt-Ergebnis des letzten invoke- kind in das angegebene Register. Dies muss als Anweisung unmittelbar nach einem invoke- kind erfolgen, dessen (Einzelwort-, Nicht-Objekt-)Ergebnis nicht ignoriert werden darf; irgendwo anders ist ungültig.
0b 11x verschiebungsergebnisweite vAA A: Zielregisterpaar (8 Bits) Verschieben Sie das Doppelwortergebnis des letzten invoke- kind in das angegebene Registerpaar. Dies muss als Anweisung unmittelbar nach einem invoke- kind erfolgen, dessen (Doppelwort-)Ergebnis nicht ignoriert werden darf; irgendwo anders ist 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 einem invoke- kind oder filled-new-array erfolgen, dessen (Objekt-)Ergebnis nicht ignoriert werden darf; irgendwo anders ist ungültig.
0d 11x Bewegungsausnahme vAA A: Zielregister (8 Bit) Speichern Sie eine gerade abgefangene Ausnahme im angegebenen Register. Dies muss die erste Anweisung eines Ausnahmebehandlers sein, dessen abgefangene Ausnahme nicht ignoriert werden soll, und diese Anweisung darf immer nur als erste Anweisung eines Ausnahmebehandlers auftreten; irgendwo anders ist ungültig.
0e 10x Rückkehr-nichtig Rückkehr von einer void Methode.
0f 11x Rückkehr vAA A: Rückgabewertregister (8 Bit) Rückgabe von einer Methode mit einfacher Breite (32 Bit), die keinen Objektwert zurückgibt.
10 11x Renditeweites vAA A: Rückgabewert Registerpaar (8 Bits) Rückgabe von einer Wertrückgabemethode mit doppelter Breite (64 Bit).
11 11x Rückgabeobjekt vAA A: Rückgabewertregister (8 Bit) Rückkehr von einer Objekt zurückgebenden Methode.
12 11n const/4 vA, #+B A: Zielregister (4 Bits)
B: vorzeichenbehafteter int (4 Bit)
Verschieben Sie den angegebenen Literalwert (vorzeichenerweitert auf 32 Bit) in das angegebene Register.
13 21s const/16 vAA, #+BBBB A: Zielregister (8 Bit)
B: signierter int (16 Bit)
Verschieben Sie den angegebenen Literalwert (vorzeichenerweitert auf 32 Bit) in das angegebene Register.
14 31i const vAA, #+BBBBBBBB A: Zielregister (8 Bit)
B: beliebige 32-Bit-Konstante
Verschieben Sie den angegebenen Literalwert in das angegebene Register.
15 21 Uhr const/high16 vAA, #+BBBB0000 A: Zielregister (8 Bit)
B: signierter int (16 Bit)
Verschieben Sie den angegebenen Literalwert (rechte Null, erweitert auf 32 Bit) in das angegebene Register.
16 21s const-wide/16 vAA, #+BBBB A: Zielregister (8 Bit)
B: signierter int (16 Bit)
Verschieben Sie den angegebenen Literalwert (vorzeichenerweitert auf 64 Bit) in das angegebene Registerpaar.
17 31i const-wide/32 vAA, #+BBBBBBBB A: Zielregister (8 Bit)
B: signierter int (32 Bit)
Verschieben Sie den angegebenen Literalwert (vorzeichenerweitert auf 64 Bit) in das angegebene Registerpaar.
18 51l const-wide vAA, #+BBBBBBBBBBBBBBBB A: Zielregister (8 Bit)
B: beliebige Konstante mit doppelter Breite (64 Bit).
Verschieben Sie den angegebenen Literalwert in das angegebene Registerpaar.
19 21 Uhr const-wide/high16 vAA, #+BBBB000000000000 A: Zielregister (8 Bit)
B: signierter int (16 Bit)
Verschieben Sie den angegebenen Literalwert (rechte Null, erweitert auf 64 Bit) in das angegebene Registerpaar.
1a 21c const-string vAA, string@BBBB A: Zielregister (8 Bit)
B: String-Index
Verschieben Sie einen Verweis auf die durch den angegebenen Index angegebene Zeichenfolge in das angegebene Register.
1b 31c const-string/jumbo vAA, string@BBBBBBBB A: Zielregister (8 Bit)
B: String-Index
Verschieben Sie einen Verweis auf die durch den angegebenen Index angegebene Zeichenfolge in das angegebene Register.
1c 21c const-Klasse vAA, Typ@BBBB A: Zielregister (8 Bit)
B: Typindex
Verschieben Sie einen Verweis auf die durch den angegebenen Index angegebene Klasse in das angegebene Register. Wenn der angegebene Typ primitiv ist, wird hiermit ein Verweis auf die degenerierte Klasse des primitiven Typs gespeichert.
1d 11x Monitor-Eingabe vAA A: Referenzlagerregister (8 Bit) Besorgen Sie sich den Monitor für das angegebene Objekt.
1e 11x Monitor-Ausgang vAA A: Referenzlagerregister (8 Bit) Lassen Sie den Monitor für das angezeigte Objekt los.

Hinweis: Wenn diese Anweisung eine Ausnahme auslösen muss, muss dies so geschehen, als ob der PC bereits über die Anweisung hinausgegangen wäre. Es kann nützlich sein, sich dies so vorzustellen, dass die Anweisung (in gewissem Sinne) erfolgreich ausgeführt wird und die Ausnahme nach der Anweisung ausgelöst wird, aber bevor die nächste ausgeführt werden kann. Diese Definition ermöglicht es einer Methode, einen Catch-All-Block für die Monitorbereinigung (z. B. „ finally “) als Monitorbereinigung für diesen Block selbst zu verwenden, um die willkürlichen Ausnahmen zu behandeln, die aufgrund der historischen Implementierung von Thread.stop() ausgelöst werden können Thread.stop() , während es dennoch gelingt, eine ordnungsgemäße Monitorhygiene sicherzustellen.

1f 21c Check-Cast vAA, Typ@BBBB A: Referenzlagerregister (8 Bit)
B: Typindex (16 Bit)
Wirft eine ClassCastException aus, 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 zur Laufzeit zwangsläufig fehl (d. h. es wird eine Ausnahme ausgelöst), wenn B auf einen primitiven Typ verweist.

20 22c Instanz von vA, vB, Typ@CCCC A: Zielregister (4 Bits)
B: referenzführendes Register (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, führt dies immer dazu, dass 0 gespeichert wird, wenn C auf einen primitiven Typ verweist.

21 12x Array-Länge vA, vB A: Zielregister (4 Bits)
B: Array-Referenz tragendes Register (4 Bits)
Speichern Sie im angegebenen Zielregister die Länge des angegebenen Arrays in Einträgen
22 21c vAA mit neuer Instanz, Typ@BBBB A: Zielregister (8 Bit)
B: Typindex
Erstellen Sie eine neue Instanz des angegebenen Typs und speichern Sie einen Verweis darauf im Ziel. Der Typ muss auf eine Nicht-Array-Klasse verweisen.
23 22c Neues Array vA, vB, Typ@CCCC A: Zielregister (4 Bits)
B: Größenregister
C: Typindex
Erstellen Sie ein neues Array des angegebenen Typs und der angegebenen Größe. Der Typ muss ein Array-Typ sein.
24 35c gefülltes neues Array {vC, vD, vE, vF, vG}, Typ@BBBB A: Array-Größe und Argumentwortanzahl (4 Bits)
B: Typindex (16 Bit)
C..G: Argumentregister (jeweils 4 Bits)
Erstellen Sie ein Array des angegebenen Typs und der angegebenen Größe und füllen Sie es mit den bereitgestellten Inhalten. Der Typ muss ein Array-Typ sein. Der Inhalt des Arrays muss aus einem Einzelwort bestehen (d. h. es dürfen keine Arrays vom long oder double sein, Referenztypen sind jedoch akzeptabel). Die konstruierte Instanz wird als „Ergebnis“ auf die gleiche Weise gespeichert, wie die Methodenaufrufanweisungen ihre Ergebnisse speichern. Daher muss die konstruierte Instanz mit einer unmittelbar nachfolgenden Anweisung move-result-object “ in ein Register verschoben werden (sofern sie verwendet werden soll). ).
25 3rc gefülltes-neues-Array/Bereich {vCCCC .. vNNNN}, Typ@BBBB A: Array-Größe und Argumentwortanzahl (8 Bit)
B: Typindex (16 Bit)
C: erstes Argumentregister (16 Bit)
N = A + C - 1
Erstellen Sie ein Array des angegebenen Typs und der angegebenen Größe und füllen Sie es mit den bereitgestellten Inhalten. Klarstellungen und Einschränkungen sind die gleichen wie oben beschrieben für filled-new-array .
26 31t Fill-Array-Data vAA, +BBBBBBBB (mit ergänzenden Daten wie unten im „ fill-array-data-payload Format“ angegeben) A: Array-Referenz (8 Bit)
B: vorzeichenbehafteter „Zweig“-Offset zur Tabellendaten-Pseudoanweisung (32 Bit)
Füllen Sie das angegebene Array mit den angegebenen Daten. Der Verweis muss sich auf ein Array von Grundelementen beziehen, und die Datentabelle muss vom Typ her mit diesem übereinstimmen und darf nicht mehr Elemente enthalten, als in das Array passen. Das heißt, das Array kann größer als die Tabelle sein. In diesem Fall werden nur die Anfangselemente des Arrays festgelegt, während der Rest in Ruhe bleibt.
27 11x vAA werfen A: ausnahmetragendes Register (8 Bit)
Löst die angegebene Ausnahme aus.
28 10t Gehe zu +AA A: vorzeichenbehafteter Verzweigungsoffset (8 Bit) Springen Sie unbedingt zur angegebenen Anweisung.

Hinweis: Der Verzweigungsoffset darf nicht 0 sein. (Eine Spin-Schleife kann legal entweder mit goto/32 oder durch Einfügen eines nop als Ziel vor der Verzweigung erstellt werden.)

29 20t gehe zu/16 +AAAA A: vorzeichenbehafteter Verzweigungsoffset (16 Bit)
Springen Sie unbedingt zur angegebenen Anweisung.

Hinweis: Der Verzweigungsoffset darf nicht 0 sein. (Eine Spin-Schleife kann legal entweder mit goto/32 oder durch Einfügen eines nop als Ziel vor der Verzweigung erstellt werden.)

2a 30t gehe zu/32 +AAAAAAAA A: vorzeichenbehafteter Verzweigungsoffset (32 Bit)
Springen Sie unbedingt zur angegebenen Anweisung.
2b 31t gepackter Switch vAA, +BBBBBBBB (mit ergänzenden Daten wie unten im „ packed-switch-payload Format“ angegeben) A: Registrieren Sie sich zum Testen
B: vorzeichenbehafteter „Zweig“-Offset zur Tabellendaten-Pseudoanweisung (32 Bit)
Springen Sie zu einem neuen Befehl basierend auf dem Wert im angegebenen Register und verwenden Sie dabei eine Tabelle mit Offsets, die jedem Wert in einem bestimmten ganzzahligen Bereich entsprechen, oder wechseln Sie zum nächsten Befehl, wenn keine Übereinstimmung vorliegt.
2c 31t Sparse-Switch vAA, +BBBBBBBB (mit ergänzenden Daten wie unten im „ sparse-switch-payload Format“ angegeben) A: Registrieren Sie sich zum Testen
B: vorzeichenbehafteter „Zweig“-Offset zur Tabellendaten-Pseudoanweisung (32 Bit)
Springen Sie zu einer neuen Anweisung basierend auf dem Wert im angegebenen Register, indem Sie eine geordnete Tabelle von Wert-Offset-Paaren verwenden, oder wechseln Sie zur nächsten Anweisung, wenn es keine Übereinstimmung gibt.
2d..31 23x cmp Art 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-lang
A: Zielregister (8 Bit)
B: erstes Quellregister oder Paar
C: zweites Quellregister oder -paar
Führen Sie den angegebenen Gleitkomma- oder long Vergleich durch und setzen Sie a auf 0 , wenn b == c , 1 wenn b > c , oder -1 wenn b < c . Der für die Gleitkommaoperationen aufgeführte „Bias“ gibt an, wie NaN Vergleiche behandelt werden: „gt-Bias“-Anweisungen geben 1 für NaN Vergleiche zurück und „lt-Bias“-Anweisungen geben -1 zurück.

Um beispielsweise zu prüfen, ob Gleitkomma x < y ist, empfiehlt sich die Verwendung cmpg-float ; Ein Ergebnis von -1 zeigt an, dass der Test wahr war, und die anderen Werte zeigen an, dass er falsch war, entweder aufgrund eines gültigen Vergleichs oder weil einer der Werte NaN war.

32..37 22t if- Test vA, vB, +CCCC
32: if-eq
33: wenn-nein
34: if-lt
35: if-ge
36: if-gt
37: if-le
A: erstes zu testendes Register (4 Bits)
B: zweites zu testendes Register (4 Bits)
C: vorzeichenbehafteter Zweigoffset (16 Bit)
Verzweigt zum angegebenen Ziel, wenn die Werte der beiden angegebenen Register wie angegeben übereinstimmen.

Hinweis: Der Verzweigungsoffset darf nicht 0 sein. (Eine Spin-Schleife kann legal konstruiert werden, indem man entweder um ein Rückwärts- goto herum verzweigt oder indem man vor der Verzweigung ein nop als Ziel einfügt.)

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

Hinweis: Der Verzweigungsoffset darf nicht 0 sein. (Eine Spin-Schleife kann legal konstruiert werden, indem man entweder um ein Rückwärts- goto herum verzweigt oder indem man vor der Verzweigung ein nop als Ziel einfügt.)

3e..43 10x (ungebraucht) (ungebraucht)
44..51 23x Arrayop vAA, vBB, vCC
44: Alter
45: altersweit
46: aget-object
47: aget-boolean
48: Aget-Byte
49: aget-char
4a: alterskurz
4b: aput
4c: aput-weit
4d: aput-Objekt
4e: aput-boolean
4f: aput-byte
50: aput-char
51: aput-kurz
A: Wertregister oder -paar; kann Quelle oder Ziel sein (8 Bit)
B: Array-Register (8 Bit)
C: Indexregister (8 Bit)
Führen Sie die identifizierte Array-Operation am identifizierten Index des angegebenen Arrays aus und laden oder speichern Sie es im Wertregister.
52..5f 22c i Instanzop vA, vB, field@CCCC
52: iget
53: iget-wide
54: iget-Objekt
55: iget-boolean
56: iget-byte
57: iget-char
58: iget-short
59: iput
5a: iput-weit
5b: Iput-Objekt
5c: iput-boolean
5d: Iput-Byte
5e: iput-char
5f: iput-short
A: Wertregister oder -paar; kann Quelle oder Ziel sein (4 Bits)
B: Objektregister (4 Bit)
C: Instanzfeld-Referenzindex (16 Bit)
Führen Sie die Operation „Identifiziertes Objektinstanzfeld“ mit dem identifizierten Feld aus und laden oder speichern Sie es im Wertregister.

Hinweis: Diese Opcodes sind sinnvolle Kandidaten für die statische Verknüpfung, da sie das Feldargument so ändern, dass es einen direkteren Offset ergibt.

60..6d 21c s staticop vAA, field@BBBB
60: get
61: get-wide
62: Sget-Objekt
63: sget-boolean
64: Sget-Byte
65: get-char
66: get-short
67: spucken
68: spuckweit
69: Sput-Objekt
6a: sput-boolean
6b: Sput-Byte
6c: Sput-Char
6d: Sput-Short
A: Wertregister oder -paar; kann Quelle oder Ziel sein (8 Bit)
B: statischer Feldreferenzindex (16 Bit)
Führen Sie die Operation für das identifizierte statische Objektobjekt mit dem identifizierten statischen Feld aus und laden oder speichern Sie es im Wertregister.

Hinweis: Diese Opcodes sind sinnvolle Kandidaten für die statische Verknüpfung, da sie das Feldargument so ändern, dass es einen direkteren Offset ergibt.

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

invoke-virtual wird verwendet, um eine normale virtuelle Methode aufzurufen (eine Methode, die nicht private , static oder final ist und auch kein Konstruktor ist).

Wenn die method_id auf eine Methode einer Nicht-Schnittstellenklasse verweist, wird invoke-super verwendet, um die virtuelle Methode der nächstgelegenen Oberklasse aufzurufen (im Gegensatz zu der Methode mit derselben method_id in der aufrufenden Klasse). Es gelten die gleichen Methodeneinschränkungen wie für invoke-virtual .

Wenn sich method_id in Dex-Dateien ab Version 037 auf eine Schnittstellenmethode bezieht, wird invoke-super verwendet, um die spezifischste, nicht überschriebene Version dieser Methode aufzurufen, die auf dieser Schnittstelle definiert ist. Es gelten die gleichen Methodeneinschränkungen wie für invoke-virtual . In Dex-Dateien vor Version 037 ist das Vorhandensein einer Schnittstelle method_id illegal und undefiniert.

invoke-direct wird verwendet, um eine nicht- static direkte Methode aufzurufen (d. h. eine Instanzmethode, die ihrer Natur nach nicht überschreibbar ist, nämlich entweder eine private Instanzmethode oder einen Konstruktor).

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

invoke-interface wird verwendet, um eine interface aufzurufen, d. h. für ein Objekt, dessen konkrete Klasse nicht bekannt ist, unter Verwendung einer method_id , die auf eine interface verweist.

Hinweis: Diese Opcodes sind sinnvolle Kandidaten für die statische Verknüpfung, indem sie das Methodenargument so ändern, dass es ein direkterer Offset (oder ein Paar davon) ist.

73 10x (ungebraucht) (ungebraucht)
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: Aufrufschnittstelle/Bereich
A: Argumentwortanzahl (8 Bits)
B: Methodenreferenzindex (16 Bit)
C: erstes Argumentregister (16 Bit)
N = A + C - 1
Rufen Sie die angegebene Methode auf. Einzelheiten, Vorbehalte und Vorschläge finden Sie in der Beschreibung der ersten invoke- kind oben.
79..7a 10x (ungebraucht) (ungebraucht)
7b..8f 12x unop vA, vB
7b: neg-int
7c: nicht-int
7d: neg-lang
7e: nicht lang
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: doppelt bis lang
8c: Double-to-Float
8d: Int-zu-Byte
8e: int-to-char
8f: int-to-short
A: Zielregister oder Zielpaar (4 Bits)
B: Quellregister oder -paar (4 Bits)
Führen Sie die identifizierte unäre Operation im Quellregister aus und speichern Sie das Ergebnis im Zielregister.
90..af 23x binop vAA, vBB, vCC
90: Add-Int
91: Unterint
92: mul-int
93: div-int
94: rem-int
95: und-int
96: or-int
97: xor-int
98: shl-int
99: shr-int
9a: ushr-int
9b: add-long
9c: sublang
9d: mul-lang
9e: div-lang
9f: rem-lang
a0: und-lang
a1: oder-lang
a2: xor-lang
a3: Shl-lang
a4: shr-lang
a5: ushr-lang
a6: Add-Float
a7: Unterschwimmer
a8: Mul-Float
a9: div-float
aa: rem-float
ab: add-double
ac: Sub-Double
Anzeige: Mul-Double
ae: div-double
af: rem-double
A: Zielregister oder Zielpaar (8 Bits)
B: erstes Quellregister oder Paar (8 Bits)
C: zweites Quellregister oder -paar (8 Bits)
Führen Sie die identifizierte Binäroperation an den beiden Quellregistern durch und speichern Sie das Ergebnis im Zielregister.

Hinweis: Im Gegensatz zu anderen -long mathematischen Operationen (die Registerpaare sowohl für ihre erste als auch für ihre zweite Quelle benötigen) verwenden shl-long , shr-long und ushr-long ein Registerpaar für ihre erste Quelle (den zu verschiebenden Wert). ), sondern ein einziges Register für ihre zweite Quelle (die Verschiebungsdistanz).

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
sein: 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
vgl.: rem-double/2addr
A: Ziel- und erstes Quellregister oder -paar (4 Bits)
B: zweites Quellregister oder -paar (4 Bits)
Führen Sie die identifizierte Binäroperation an den beiden Quellregistern durch und speichern Sie das Ergebnis im ersten Quellregister.

Hinweis: Im Gegensatz zu anderen mathematischen Operationen -long/2addr (die Registerpaare sowohl für ihr Ziel/erste Quelle als auch für ihre zweite Quelle benötigen) nehmen shl-long/2addr , shr-long/2addr und ushr-long/2addr ein Register Paar für ihr Ziel/erste Quelle (der zu verschiebende Wert), aber ein einzelnes Register für ihre zweite Quelle (die Verschiebungsentfernung).

d0..d7 22s binop /lit16 vA, vB, #+CCCC
d0: add-int/lit16
d1: rsub-int (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 Bits)
B: Quellregister (4 Bits)
C: Vorzeichenbehaftete int-Konstante (16 Bit)
Führen Sie die angegebene binäre Operation für das angegebene Register (erstes Argument) und den Literalwert (zweites Argument) aus und speichern Sie das Ergebnis im Zielregister.

Hinweis: rsub-int hat kein Suffix, da diese Version der Haupt-Opcode seiner Familie ist. Einzelheiten zur Semantik finden Sie weiter 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: Vorzeichenbehaftete int-Konstante (8 Bit)
Führen Sie die angegebene binäre Operation für das angegebene Register (erstes Argument) und den Literalwert (zweites Argument) aus und speichern Sie das Ergebnis im Zielregister.

Hinweis: Einzelheiten zur Semantik von rsub-int finden Sie weiter unten.

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

Der Methodenverweis muss auf eine polymorphe Signaturmethode verweisen, z. B. java.lang.invoke.MethodHandle.invoke oder java.lang.invoke.MethodHandle.invokeExact .

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

Die Prototypreferenz beschreibt die bereitgestellten Argumenttypen und den erwarteten Rückgabetyp.

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

In Dex-Dateien ab Version 038 vorhanden.
fb 4rcc invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH A: Argumentwortanzahl (8 Bits)
B: Methodenreferenzindex (16 Bit)
C: Empfänger (16 Bit)
H: Prototyp-Referenzindex (16 Bit)
N = A + C - 1
Rufen Sie das angegebene Methodenhandle auf. Weitere Informationen finden Sie in der obigen Beschreibung invoke-polymorphic .

In Dex-Dateien ab Version 038 vorhanden.
fc 35c invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB A: Argumentwortanzahl (4 Bits)
B: Referenzindex der Aufrufstelle (16 Bit)
C..G: Argumentregister (jeweils 4 Bits)
Löst die angegebene Aufrufseite auf und ruft sie auf. Das Ergebnis des Aufrufs (falls vorhanden) kann mit einer entsprechenden move-result* -Variante als unmittelbar nachfolgende Anweisung gespeichert werden.

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

Bei der Call-Site-Auflösung wird geprüft, ob der angegebenen Call-Site eine java.lang.invoke.CallSite Instanz zugeordnet ist. Wenn nicht, wird die Bootstrap-Linker-Methode für die angegebene Aufruf-Site mithilfe der in der DEX-Datei vorhandenen Argumente aufgerufen (siehe call_site_item ). Die Bootstrap-Linker-Methode gibt eine java.lang.invoke.CallSite Instanz zurück, die dann mit der angegebenen Aufruf-Site verknüpft wird, wenn keine Zuordnung besteht. Möglicherweise hat ein anderer Thread die Zuordnung bereits zuerst vorgenommen. Wenn dies der Fall ist, wird die Ausführung der Anweisung mit der ersten zugeordneten java.lang.invoke.CallSite Instanz fortgesetzt.

Der Aufruf der Aufrufsite 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 (oben beschrieben) ausgeführt, wobei das Methodenhandle und die Argumente für die invoke-custom Anweisung als Argumente für einen exakten Methodenhandle-Aufruf verwendet werden.

Von der Bootstrap-Linker-Methode ausgelöste Ausnahmen werden in einen java.lang.BootstrapMethodError eingeschlossen. Ein BootstrapMethodError wird auch ausgelöst, wenn:
  • Die Bootstrap-Linker-Methode kann keine java.lang.invoke.CallSite Instanz zurückgeben.
  • Die zurückgegebene java.lang.invoke.CallSite hat ein null Methodenhandle-Ziel.
  • Das Methodenhandle-Ziel ist nicht vom angeforderten Typ.
In Dex-Dateien ab Version 038 vorhanden.
fd 3rc invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB A: Argumentwortanzahl (8 Bits)
B: Referenzindex der Aufrufstelle (16 Bit)
C: erstes Argumentregister (16 Bit)
N = A + C - 1
Lösen Sie eine Anrufseite auf und rufen Sie sie auf. Weitere Informationen finden Sie oben in der Beschreibung invoke-custom .

In Dex-Dateien ab Version 038 vorhanden.
Fe 21c const-method-handle vAA, method_handle@BBBB A: Zielregister (8 Bit)
B: Methodenhandle-Index (16 Bit)
Verschieben Sie einen Verweis auf das durch den angegebenen Index angegebene Methodenhandle 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)
Verschieben Sie einen Verweis auf den durch den angegebenen Index angegebenen Methodenprototyp in das angegebene Register.

In Dex-Dateien ab Version 039 vorhanden.

Packed-Switch-Payload-Format

Name Format Beschreibung
Ident ushort = 0x0100 Identifizierung von Pseudo-Opcode
Größe ushort Anzahl der Einträge in der Tabelle
erster_schlüssel int erster (und niedrigster) Schaltfallwert
Ziele int[] Liste der size Verzweigungsziele. Die Ziele beziehen sich auf die Adresse des Switch-Opcodes, nicht auf die Adresse dieser Tabelle.

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

Sparse-Switch-Payload-Format

Name Format Beschreibung
ident ushort = 0x0200 Identifizierung von Pseudo-Opcode
Größe ushort Anzahl der Einträge in der Tabelle
Schlüssel int[] Liste der size , sortiert von niedrig nach hoch
Ziele int[] Liste der size Verzweigungsziele, die jeweils dem Schlüsselwert am gleichen Index entsprechen. Die Ziele beziehen sich auf die Adresse des Switch-Opcodes, nicht auf die Adresse dieser Tabelle.

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

Fill-Array-Data-Payload-Format

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

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

Einzelheiten zur mathematischen Operation

Hinweis: Gleitkommaoperationen müssen den IEEE 754-Regeln folgen und auf den nächsten Wert runden und einen allmählichen Unterlauf verwenden, sofern nicht anders angegeben.

Opcode C-Semantik Anmerkungen
neg-int int32 a;
int32 Ergebnis = -a;
Unäres Zweierkomplement.
nicht-int int32 a;
int32 result = ~a;
Unäres Einserkomplement.
neg-lang int64 a;
int64 Ergebnis = -a;
Unäres Zweierkomplement.
nicht lang int64 a;
int64 result = ~a;
Unäres Einserkomplement.
Neg-Float float a;
float result = -a;
Gleitkomma-Negation.
neg-double Doppel a;
doppeltes Ergebnis = -a;
Gleitkomma-Negation.
int-to-long int32 a;
int64 result = (int64) a;
Signieren Sie die Erweiterung von int32 in int64 .
Int-to-to-to-Float int32 a;
float result = (float) a;
Umwandlung von int32 zum float mit rund-zu-Nearest. Dies verliert Präzision für einige Werte.
int-to-double int32 a;
Doppelergebnis = (doppelt) a;
Umwandlung von int32 in double .
lang zu int int64 a;
int32 result = (int32) a;
Kürzung von int64 in int32 .
lang zu flotten int64 a;
float result = (float) a;
Umwandlung von int64 zum float mit rund-zu-Nearest. Dies verliert Präzision für einige Werte.
lang zu double int64 a;
Doppelergebnis = (doppelt) a;
Umwandlung von int64 in double , unter Verwendung von rund zu Nearest. Dies verliert Präzision für einige Werte.
float-to-in float a;
int32 result = (int32) a;
Konvertierung von float in int32 mit Rundzusammenfordern-Null. NaN und -0.0 (negativer Null) konvertieren in die Ganzzahl 0 . Unendlichkeiten und Werte mit zu großer Größe, um dargestellt zu werden, werden je nach Zeichen entweder in 0x7fffffff oder -0x80000000 umgewandelt.
float-to-long float a;
int64 result = (int64) a;
Konvertierung von float in int64 mit Rundzusammenstellungsnull. Die gleichen Sonderfallregeln wie für float-to-int Ins jedoch jedoch jedoch, dass außerhalb des Bereichs je nach Zeichen entweder in 0x7fffffffffffffff oder -0x80000000000000 oder -0x8000000000000000 konvertiert wird.
Float-to-Double float a;
Doppelergebnis = (doppelt) a;
Umwandlung von float zu double und genau den Wert erhalten.
doppelt zu int Doppel a;
int32 result = (int32) a;
Umwandlung von double in int32 mit Rundzahlen-Null. Die gleichen Sonderfallregeln wie für float-to-int hier gelten hier.
doppelt zu lang Doppel a;
int64 result = (int64) a;
Umwandlung von double in int64 mit Rundzahlen-Null. Die gleichen Sonderfallregeln wie für float-to-long hier gelten.
doppelt flott Doppel a;
float result = (float) a;
Umwandlung von double zum float mit rund-zu-Nearst. Dies verliert Präzision für einige Werte.
int-to-byte int32 a;
int32 result = (a << 24) >> 24;
Kürzung von int32 bis int8 , Zeichen, die das Ergebnis erweitert.
int-to-char int32 a;
int32 result = a & 0xffff;
Kürzung von int32 bis uint16 ohne Vorzeichenverlängerung.
int-to-Short int32 a;
int32 result = (a << 16) >> 16;
Kürzung von int32 bis int16 , Zeichen, die das Ergebnis erweitert.
Add-Int int32 a, b;
int32 result = a + b;
Zwei-Komplement-Addition.
sub-in int32 a, b;
int32 result = a - b;
Zwei-Komplement-Subtraktion.
rsub-int int32 a, b;
int32 result = b - a;
Zwei-Komplement-Reverse-Subtraktion.
Mul-in int32 a, b;
int32 result = a * b;
Zwei-Komplement-Multiplikation.
div-in int32 a, b;
int32 result = a / b;
Zwei-Komplement-Division, abgerundet auf Null abgerundet (dh an Ganzzahl abgeschnitten). Dies wirft ArithmeticException aus, wenn b == 0 .
rem-in int32 a, b;
INT32 Ergebnis = A % b;
Zwei-Komplement-Rest nach der Division. Das Zeichen des Ergebnisses ist das gleiche wie das von a und ist genauer wie result == a - (a / b) * b . Dies wirft ArithmeticException aus, wenn b == 0 .
und-in int32 a, b;
int32 result = a & b;
Bitweise und.
or-in int32 a, b;
int32 result = a | B;
Bitweise oder.
xor-int int32 a, b;
int32 result = a ^ b;
Bitweise xor.
Shl-in int32 a, b;
int32 result = a << (B & 0x1f);
Bitweise Verschiebung nach links (mit maskierter Argument).
Shr-Int int32 a, b;
int32 result = a >> (b & 0x1f);
Bitweise signierte Verschiebung rechts (mit maskiertem Argument).
ushr-int uint32 a, b;
int32 result = a >> (b & 0x1f);
Bitgewise Unsigned Verschiebung rechts (mit maskiertem Argument).
Fügen Sie long int64 a, b;
int64 result = a + b;
Zwei-Komplement-Addition.
sublong int64 a, b;
int64 result = a - b;
Zwei-Komplement-Subtraktion.
mullong int64 a, b;
int64 result = a * b;
Zwei-Komplement-Multiplikation.
Div-Long int64 a, b;
int64 result = a / b;
Zwei-Komplement-Division, abgerundet auf Null abgerundet (dh an Ganzzahl abgeschnitten). Dies wirft ArithmeticException aus, wenn b == 0 .
rem-long int64 a, b;
int64 Ergebnis = A % b;
Zwei-Komplement-Rest nach der Division. Das Zeichen des Ergebnisses ist das gleiche wie das von a und ist genauer wie result == a - (a / b) * b . Dies wirft ArithmeticException aus, wenn b == 0 .
und lang int64 a, b;
int64 result = a & b;
Bitweise und.
oder long int64 a, b;
int64 result = a | B;
Bitweise oder.
xor-long int64 a, b;
int64 result = a ^ b;
Bitweise xor.
SHL-Long int64 a;
int32 b;
int64 result = a << (B & 0x3f);
Bitweise Verschiebung nach links (mit maskierter Argument).
Shrlong int64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Bitweise signierte Verschiebung rechts (mit maskiertem Argument).
USHR-Long uint64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Bitgewise Unsigned Verschiebung rechts (mit maskiertem Argument).
Add-Float float a, b;
float result = a + b;
Schwebende Punktzusatz.
Unterfloat float a, b;
float result = a - b;
Schwimmende Punktsubtraktion.
Mul-Float float a, b;
float result = a * b;
Schwimmende Punktmultiplikation.
Div-Float float a, b;
float result = a / b;
Schwebende Punktdivision.
Rem-Float float a, b;
Float -Ergebnis = A % b;
Schwebender Punkt nach der Teilung. Diese Funktion ist anders als IEEE 754 Rest und wird als result == a - roundTowardZero(a / b) * b definiert.
Addouble Doppel A, B;
Doppelergebnis = a + b;
Schwebende Punktzusatz.
Subdouble Doppel A, B;
Doppelergebnis = a - b;
Schwimmende Punktsubtraktion.
Mul-Double Doppel A, B;
doppeltes Ergebnis = a * b;
Schwimmende Punktmultiplikation.
div-double Doppel A, B;
Doppelergebnis = a / b;
Schwebende Punktdivision.
Rem-Double Doppel A, B;
Doppelergebnis = A % B;
Schwebender Punkt nach der Teilung. Diese Funktion ist anders als IEEE 754 Rest und wird als result == a - roundTowardZero(a / b) * b definiert.