Conception générale
- Le modèle de machine et les conventions d'appel sont censés imiter approximativement les architectures réelles courantes et les conventions d'appel de style C :
- La machine est basée sur les registres et les cadres sont de taille fixe lors de la création. Chaque trame se compose d'un nombre particulier de registres (spécifié par la méthode) ainsi que de toutes les données complémentaires nécessaires pour exécuter la méthode, telles que (mais sans s'y limiter) le compteur de programme et une référence au fichier
.dex
qui contient la méthode . - Lorsqu'ils sont utilisés pour des valeurs binaires (telles que des nombres entiers et des nombres à virgule flottante), les registres sont considérés comme ayant une largeur de 32 bits. Des paires de registres adjacentes sont utilisées pour les valeurs 64 bits. Il n'y a aucune exigence d'alignement pour les paires de registres.
- Lorsqu'ils sont utilisés pour des références d'objets, les registres sont considérés comme suffisamment larges pour contenir exactement une telle référence.
- En termes de représentation au niveau du bit,
(Object) null == (int) 0
. - Les N arguments d'une méthode atterrissent dans les N derniers registres de la trame d'invocation de la méthode, dans l'ordre. Les arguments larges consomment deux registres. Les méthodes d'instance reçoivent une référence
this
comme premier argument.
- La machine est basée sur les registres et les cadres sont de taille fixe lors de la création. Chaque trame se compose d'un nombre particulier de registres (spécifié par la méthode) ainsi que de toutes les données complémentaires nécessaires pour exécuter la méthode, telles que (mais sans s'y limiter) le compteur de programme et une référence au fichier
- L'unité de stockage dans le flux d'instructions est une quantité non signée de 16 bits. Certains bits de certaines instructions sont ignorés / doivent être nuls.
- Les instructions ne sont pas gratuitement limitées à un type particulier. Par exemple, les instructions qui déplacent des valeurs de registre 32 bits sans interprétation n'ont pas à spécifier si elles déplacent des entiers ou des flottants.
- Il existe des pools de constantes énumérées et indexées séparément pour les références aux chaînes, types, champs et méthodes.
- Les données littérales au niveau du bit sont représentées en ligne dans le flux d'instructions.
- Parce qu'en pratique, il est rare qu'une méthode ait besoin de plus de 16 registres, et parce qu'il est raisonnablement courant d'avoir besoin de plus de huit registres, de nombreuses instructions se limitent à adresser uniquement les 16 premiers registres. Lorsque cela est raisonnablement possible, les instructions autorisent les références jusqu'aux 256 premiers registres. De plus, certaines instructions ont des variantes qui permettent un nombre de registres beaucoup plus important, y compris une paire d'instructions de
move
fourre-tout qui peuvent adresser des registres dans la plagev0
–v65535
. Dans les cas où une variante d'instruction n'est pas disponible pour adresser un registre souhaité, il est prévu que le contenu du registre soit déplacé du registre d'origine vers un registre bas (avant l'opération) et/ou déplacé d'un registre de résultat bas vers un registre haut. enregistrer (après l'opération). - Il existe plusieurs "pseudo-instructions" qui sont utilisées pour contenir des charges utiles de données de longueur variable, qui sont référencées par des instructions régulières (par exemple,
fill-array-data
). De telles instructions ne doivent jamais être rencontrées pendant le déroulement normal de l'exécution. De plus, les instructions doivent être situées sur des décalages de code octet pairs (c'est-à-dire alignés sur 4 octets). Afin de répondre à cette exigence, les outils de génération de dex doivent émettre une instructionnop
supplémentaire en tant qu'espaceur si une telle instruction serait autrement non alignée. Enfin, bien que ce ne soit pas obligatoire, on s'attend à ce que la plupart des outils choisissent d'émettre ces instructions à la fin des méthodes, car sinon, il serait probable que des instructions supplémentaires soient nécessaires pour les contourner. - Lorsqu'elles sont installées sur un système en cours d'exécution, certaines instructions peuvent être modifiées, en modifiant leur format, en tant qu'optimisation de liaison statique au moment de l'installation. Cela permet une exécution plus rapide une fois que la liaison est connue. Voir le document des formats d'instructions associés pour les variantes suggérées. Le mot "suggéré" est utilisé à bon escient; il n'est pas obligatoire de les mettre en œuvre.
- Syntaxe humaine et mnémoniques :
- Classement destination-puis-source pour les arguments.
- Certains opcodes ont un suffixe de nom désambiguïsant pour indiquer le ou les types sur lesquels ils opèrent :
- Les opcodes 32 bits de type général ne sont pas marqués.
- Les opcodes 64 bits de type général sont suffixés par
-wide
. - Les opcodes spécifiques au type sont suffixés avec leur type (ou une abréviation directe), l'un des suivants :
-boolean
-byte
-char
-short
-int
-long
-float
-double
-object
-string
-class
-void
.
- Certains opcodes ont un suffixe de désambiguïsation pour distinguer des opérations par ailleurs identiques qui ont des dispositions ou des options d'instructions différentes. Ces suffixes sont séparés des noms principaux par une barre oblique ("
/
") et existent principalement pour faire en sorte qu'il y ait un mappage un à un avec des constantes statiques dans le code qui génère et interprète les exécutables (c'est-à-dire pour réduire l'ambiguïté pour les humains). - Dans les descriptions ici, la largeur d'une valeur (indiquant par exemple la plage d'une constante ou le nombre de registres éventuellement adressés) est accentuée par l'utilisation d'un caractère par quatre bits de largeur.
- Par exemple, dans l'instruction "
move-wide/from16 vAA, vBBBB
" :- "
move
" est l'opcode de base, indiquant l'opération de base (déplacer la valeur d'un registre). - "
wide
" est le suffixe du nom, indiquant qu'il fonctionne sur des données larges (64 bits). - "
from16
" est le suffixe d'opcode, indiquant une variante qui a une référence de registre 16 bits comme source. - "
vAA
" est le registre de destination (implicite par l'opération ; encore une fois, la règle est que les arguments de destination viennent toujours en premier), qui doit être dans la plagev0
–v255
. - "
vBBBB
" est le registre source, qui doit être dans la plagev0
–v65535
.
- "
- Voir le document sur les formats d'instructions pour plus de détails sur les différents formats d'instructions (répertoriés sous "Op & Format") ainsi que des détails sur la syntaxe de l'opcode.
- Voir le document sur le format de fichier
.dex
pour plus de détails sur la place du bytecode dans l'image plus grande.
Résumé du jeu de bytecodes
Opération & Format | Mnémonique / Syntaxe | Arguments | La description |
---|---|---|---|
00 10x | non | Cycles de déchets. Remarque : Les pseudo-instructions portant des données sont étiquetées avec cet opcode, auquel cas l'octet de poids fort de l'unité d'opcode indique la nature des données. Voir "Format | |
01 12x | déplacer vA, vB | A: registre de destination (4 bits)B: registre source (4 bits) | Déplacer le contenu d'un registre non objet vers un autre. |
02 22x | déplacer/depuis16 vAA, vBBBB | A: registre de destination (8 bits)B: registre source (16 bits) | Déplacer le contenu d'un registre non objet vers un autre. |
03 32x | mouvement/16 vAAAA, vBBBB | A: registre de destination (16 bits)B: registre source (16 bits) | Déplacer le contenu d'un registre non objet vers un autre. |
04 12x | déplacer à l'échelle vA, vB | A: paire de registres de destination (4 bits)B: paire de registres source (4 bits) | Déplacer le contenu d'une paire de registres vers une autre. Remarque : Il est légal de passer de |
05 22x | déplacer à l'échelle/à partir de16 vAA, vBBBB | A: paire de registres de destination (8 bits)B: paire de registres source (16 bits) | Déplacer le contenu d'une paire de registres vers une autre. Remarque : les considérations d'implémentation sont les mêmes que pour |
06 32x | déplacer à l'échelle / 16 vAAAA, vBBBB | A: paire de registres de destination (16 bits)B: paire de registres source (16 bits) | Déplacer le contenu d'une paire de registres vers une autre. Remarque : les considérations d'implémentation sont les mêmes que pour |
07 12x | déplacer-objet vA, vB | A: registre de destination (4 bits)B: registre source (4 bits) | Déplacer le contenu d'un registre porteur d'objets vers un autre. |
08 22x | déplacer-objet/depuis16 vAA, vBBBB | A: registre de destination (8 bits)B: registre source (16 bits) | Déplacer le contenu d'un registre porteur d'objets vers un autre. |
09 32x | déplacer-objet/16 vAAAA, vBBBB | A: registre de destination (16 bits)B: registre source (16 bits) | Déplacer le contenu d'un registre porteur d'objets vers un autre. |
0a 11x | mouvement-résultat vAA | A: registre de destination (8 bits) | Déplacez le résultat non objet à mot unique du invoke- kind le plus récent dans le registre indiqué. Cela doit être fait comme l'instruction immédiatement après un invoke- kind dont le résultat (mot unique, non objet) ne doit pas être ignoré ; n'importe où ailleurs est invalide. |
0b 11x | vAA à l'échelle du résultat de déplacement | A: paire de registres de destination (8 bits) | Déplacez le résultat du mot double du invoke- kind le plus récent dans la paire de registres indiquée. Cela doit être fait comme l'instruction immédiatement après un invoke- kind dont le résultat (mot double) ne doit pas être ignoré ; n'importe où ailleurs est invalide. |
0c 11x | move-result-object vAA | A: registre de destination (8 bits) | Déplacez le résultat d'objet du invoke- kind le plus récent dans le registre indiqué. Cela doit être fait comme l'instruction immédiatement après un invoke- kind d'appel ou filled-new-array dont le résultat (objet) ne doit pas être ignoré ; n'importe où ailleurs est invalide. |
0d 11x | move-exception vAA | A: registre de destination (8 bits) | Enregistrer une exception qui vient d'être interceptée dans le registre donné. Il doit s'agir de la première instruction de tout gestionnaire d'exceptions dont l'exception interceptée ne doit pas être ignorée, et cette instruction ne doit apparaître que comme première instruction d'un gestionnaire d'exceptions ; n'importe où ailleurs est invalide. |
0e 10x | retour-vide | Retour d'une méthode void . | |
0f 11x | retour vAA | A: registre de valeur de retour (8 bits) | Retour à partir d'une méthode de retour de valeur non objet à largeur unique (32 bits). |
10 11x | vAA à l'échelle du retour | A: paire de registres de valeur de retour (8 bits) | Retour d'une méthode de retour de valeur double largeur (64 bits). |
11 11x | objet de retour vAA | A: registre de valeur de retour (8 bits) | Retour d'une méthode de retour d'objet. |
12 11n | const/4 vA, #+B | A: registre de destination (4 bits)B: entier signé (4 bits) | Déplace la valeur littérale donnée (signe étendu à 32 bits) dans le registre spécifié. |
13 21s | const/16 vAA, #+BBBB | A: registre de destination (8 bits)B: entier signé (16 bits) | Déplace la valeur littérale donnée (signe étendu à 32 bits) dans le registre spécifié. |
14 31i | const vAA, #+BBBBBBBB | A: registre de destination (8 bits)B: constante arbitraire de 32 bits | Déplace la valeur littérale donnée dans le registre spécifié. |
15 21h | const/élevé16 vAA, #+BBBB0000 | A: registre de destination (8 bits)B: entier signé (16 bits) | Déplace la valeur littérale donnée (zéro droit étendu à 32 bits) dans le registre spécifié. |
16 21s | const-wide/16 vAA, #+BBBB | A: registre de destination (8 bits)B: entier signé (16 bits) | Déplacez la valeur littérale donnée (signe étendu à 64 bits) dans la paire de registres spécifiée. |
17 31i | const-wide/32 vAA, #+BBBBBBBB | A: registre de destination (8 bits)B: entier signé (32 bits) | Déplacez la valeur littérale donnée (signe étendu à 64 bits) dans la paire de registres spécifiée. |
18 51l | const-wide vAA, #+BBBBBBBBBBBBBBBB | A: registre de destination (8 bits)B: constante arbitraire à double largeur (64 bits) | Déplacez la valeur littérale donnée dans la paire de registres spécifiée. |
19 21h | const-wide/high16 vAA, #+BBBB000000000000 | A: registre de destination (8 bits)B: entier signé (16 bits) | Déplacez la valeur littérale donnée (zéro droit étendu à 64 bits) dans la paire de registres spécifiée. |
1a 21c | chaîne const vAA, chaîne@BBBB | A: registre de destination (8 bits)B: indice de chaîne | Déplace une référence à la chaîne spécifiée par l'index donné dans le registre spécifié. |
1b 31c | chaîne const/jumbo vAA, chaîne@BBBBBBBB | A: registre de destination (8 bits)B: indice de chaîne | Déplace une référence à la chaîne spécifiée par l'index donné dans le registre spécifié. |
1c 21c | const-classe vAA, type@BBBB | A: registre de destination (8 bits)B: indice des types | Déplace une référence à la classe spécifiée par l'index donné dans le registre spécifié. Dans le cas où le type indiqué est primitif, cela stockera une référence à la classe dégénérée du type primitif. |
1j 11x | moniteur-entrer vAA | A: registre de référence (8 bits) | Acquérir le moniteur pour l'objet indiqué. |
1e 11x | moniteur-sortie vAA | A: registre de référence (8 bits) | Relâchez le moniteur pour l'objet indiqué. Remarque : Si cette instruction doit lever une exception, elle doit le faire comme si le pc avait déjà dépassé l'instruction. Il peut être utile de considérer cela comme l'instruction s'exécutant avec succès (dans un sens) et l'exception levée après l'instruction mais avant que la suivante n'ait la chance de s'exécuter. Cette définition permet à une méthode d'utiliser un bloc fourre-tout de nettoyage de moniteur (par exemple, |
1f 21c | check-cast vAA, type@BBBB | A: registre de référence (8 bits)B: indice de type (16 bits) | Levez une ClassCastException si la référence dans le registre donné ne peut pas être convertie en type indiqué. Remarque : puisque |
20 22c | instance de vA, vB, type@CCCC | A: registre de destination (4 bits)B: registre de référence (4 bits)C: indice de type (16 bits) | Stocke dans le registre de destination donné 1 si la référence indiquée est une instance du type donné, ou 0 sinon. Remarque : puisque |
21 12x | longueur de tableau vA, vB | A: registre de destination (4 bits)B: registre porte-référence tableau (4 bits) | Stocke dans le registre de destination donné la longueur du tableau indiqué, en entrées |
22 21c | nouvelle instance vAA, type@BBBB | A: registre de destination (8 bits)B: indice des types | Construire une nouvelle instance du type indiqué, en stockant une référence à celle-ci dans la destination. Le type doit faire référence à une classe non tableau. |
23 22c | nouvelle matrice vA, vB, type@CCCC | A: registre de destination (4 bits)B: registre de tailleC: indice des types | Construisez un nouveau tableau du type et de la taille indiqués. Le type doit être un type tableau. |
24 35c | rempli-nouveau-tableau {vC, vD, vE, vF, vG}, type@BBBB | A: taille du tableau et nombre de mots d'argument (4 bits)B: indice de type (16 bits)C..G: registres d'arguments (4 bits chacun) | Construire un tableau du type et de la taille donnés, en le remplissant avec le contenu fourni. Le type doit être un type tableau. Le contenu du tableau doit être composé d'un seul mot (c'est-à-dire qu'il n'y a pas de tableaux long ou double , mais les types de référence sont acceptables). L'instance construite est stockée en tant que "résultat" de la même manière que les instructions d'invocation de méthode stockent leurs résultats, de sorte que l'instance construite doit être déplacée vers un registre avec une instruction move-result-object immédiatement suivante (si elle doit être utilisée ). |
25 3rc | rempli-nouveau-tableau/plage {vCCCC .. vNNNN}, type@BBBB | A: taille du tableau et nombre de mots d'argument (8 bits)B: indice de type (16 bits)C: premier registre d'argument (16 bits)N = A + C - 1 | Construire un tableau du type et de la taille donnés, en le remplissant avec le contenu fourni. Les clarifications et les restrictions sont les mêmes que pour filled-new-array , décrit ci-dessus. |
26 31t | fill-array-data vAA, +BBBBBBBB (avec des données supplémentaires comme spécifié ci-dessous dans " fill-array-data-payload Format") | A: référence de tableau (8 bits)B: décalage de "branche" signé vers la pseudo-instruction de données de table (32 bits) | Remplissez le tableau donné avec les données indiquées. La référence doit être à un tableau de primitives, et la table de données doit lui correspondre en type et ne doit pas contenir plus d'éléments que ne peut en contenir le tableau. Autrement dit, le tableau peut être plus grand que la table, et si c'est le cas, seuls les éléments initiaux du tableau sont définis, laissant le reste seul. |
27 11x | jeter vAA | A: registre porteur d'exceptions (8 bits) | Lancez l'exception indiquée. |
28 10t | aller à +AA | A: décalage de branche signé (8 bits) | Sauter sans condition à l'instruction indiquée. Remarque : Le décalage de branche ne doit pas être |
29 20t | goto/16 + AAAA | A: décalage de branche signé (16 bits) | Sauter sans condition à l'instruction indiquée. Remarque : Le décalage de branche ne doit pas être |
2a 30t | goto/32 +AAAAAAAA | A: décalage de branche signé (32 bits) | Sauter sans condition à l'instruction indiquée. |
2b 31t | packed-switch vAA, +BBBBBBBB (avec des données supplémentaires comme spécifié ci-dessous dans " packed-switch-payload Format") | A: inscrivez-vous pour testerB: décalage de "branche" signé vers la pseudo-instruction de données de table (32 bits) | Sauter à une nouvelle instruction basée sur la valeur dans le registre donné, en utilisant une table de décalages correspondant à chaque valeur dans une plage intégrale particulière, ou passer à l'instruction suivante s'il n'y a pas de correspondance. |
2c 31t | sparse-switch vAA, +BBBBBBBB (avec des données supplémentaires comme spécifié ci-dessous dans le " sparse-switch-payload Format") | A: inscrivez-vous pour testerB: décalage de "branche" signé vers la pseudo-instruction de données de table (32 bits) | Sauter à une nouvelle instruction basée sur la valeur dans le registre donné, en utilisant un tableau ordonné de paires valeur-décalage, ou passer à l'instruction suivante s'il n'y a pas de correspondance. |
2j..31 23x | cmp type vAA, vBB, vCC 2d : cmpl-float (biais lt) 2e : cmpg-float (biais gt) 2f : cmpl-double (lt bias) 30 : cmpg-double (biais gt) 31 : cmp de long | A: registre de destination (8 bits)B: premier registre ou paire sourceC: deuxième registre source ou paire | Effectuez la comparaison à virgule flottante ou long indiquée, en définissant a sur 0 si b == c , 1 si b > c , ou -1 si b < c . Le "biais" répertorié pour les opérations en virgule flottante indique comment les comparaisons NaN sont traitées : les instructions "gt bias" renvoient 1 pour les comparaisons NaN , et les instructions "lt bias" renvoient -1 . Par exemple, pour vérifier si virgule flottante |
32..37 22t | si- test vA, vB, +CCCC 32: si-eq 33 : si-ne 34 : si-lt 35 : si-ge 36: si-gt 37: si-le | A: premier registre à tester (4 bits)B: deuxième registre à tester (4 bits)C: décalage de branche signé (16 bits) | Branchez-vous à la destination donnée si les valeurs des deux registres donnés se comparent comme spécifié. Remarque : Le décalage de branche ne doit pas être |
38..3d 21t | si- test z vAA, +BBBB 38 : si-eqz 39: si-nez 3a : si-ltz 3b : si-gez 3c : si-gtz 3d : si-lez | A: registre à tester (8 bits)B: décalage de branche signé (16 bits) | Branchez-vous à la destination donnée si la valeur du registre donné est comparable à 0 comme spécifié. Remarque : Le décalage de branche ne doit pas être |
3e..43 10x | (inutilisé) | (inutilisé) | |
44..51 23x | arrayop vAA, vBB, vCC 44 : ... 45 ans : à l'échelle de l'âge 46 : objet-aget 47 : aget-booléen 48 : age-octet 49: age-char 4a : age-court 4b : mettre 4c : aput à l'échelle 4d : aput-object 4e : aput-booléen 4f : un octet de saisie 50 : aput-char 51 : un put-court | A: registre ou paire de valeurs ; peut être source ou destination (8 bits)B: registre de tableau (8 bits)C: registre d'index (8 bits) | Effectuez l'opération de tableau identifiée à l'index identifié du tableau donné, en chargeant ou en stockant dans le registre de valeur. |
52..5f 22c | i instanceop vA, vB, champ@CCCC 52 : 1 53 : iget à l'échelle 54 : iget-objet 55 : iget-booléen 56 : iget-octet 57: iget-char 58 : iget-court 59 : entrée 5a : à l'échelle de l'entrée 5b : objet d'entrée 5c : entrée-booléen 5d : octet d'entrée 5e : caractère d'entrée 5f : entrée courte | A: registre ou paire de valeurs ; peut être source ou destination (4 bits)B: registre d'objet (4 bits)C: index de référence du champ d'instance (16 bits) | Effectuez l'opération de champ d'instance d'objet identifié avec le champ identifié, en chargeant ou en stockant dans le registre de valeurs. Remarque : Ces opcodes sont des candidats raisonnables pour la liaison statique, modifiant l'argument du champ pour qu'il soit un décalage plus direct. |
60..6d 21c | s statiqueop vAA , champ@BBBB 60: sget 61 : à l'échelle du sget 62 : objet sget 63 : sget-booléen 64 : sget-octet 65 : sget-char 66 : sget-court 67: cracher 68 : à l'échelle de la source 69: objet-sput 6a : sput-booléen 6b : octet de sortie 6c : sput-char 6d : craché court | A: registre ou paire de valeurs ; peut être source ou destination (8 bits)B: indice de référence de champ statique (16 bits) | Effectuez l'opération de champ statique de l'objet identifié avec le champ statique identifié, en chargeant ou en stockant dans le registre de valeurs. Remarque : Ces opcodes sont des candidats raisonnables pour la liaison statique, modifiant l'argument du champ pour qu'il soit un décalage plus direct. |
6e..72 35c | invoquer- kind {vC, vD, vE, vF, vG}, meth@BBBB 6e : appel virtuel 6f : invoquer-super 70 : invoquer-direct 71 : appel-statique 72 : invoquer l'interface | A: nombre de mots d'argument (4 bits)B: indice de référence de méthode (16 bits)C..G: registres d'arguments (4 bits chacun) | Appelez la méthode indiquée. Le résultat (le cas échéant) peut être stocké avec une variante move-result* appropriée comme instruction immédiatement suivante. Lorsque le Dans les fichiers Dex version Remarque : Ces opcodes sont des candidats raisonnables pour la liaison statique, modifiant l'argument de la méthode pour qu'il soit un décalage plus direct (ou une paire de ceux-ci). |
73 10x | (inutilisé) | (inutilisé) | |
74..78 3rc | invoquer- kind /range {vCCCC .. vNNNN}, meth@BBBB 74 : invoquer-virtuel/plage 75 : invoquer-super/gamme 76 : invoquer-direct/plage 77 : invoquer-statique/plage 78 : invoquer-interface/plage | A: nombre de mots d'argument (8 bits)B: indice de référence de méthode (16 bits)C: premier registre d'argument (16 bits)N = A + C - 1 | Appelez la méthode indiquée. Voir la description du premier invoke- kind ci-dessus pour plus de détails, des mises en garde et des suggestions. |
79..7a 10x | (inutilisé) | (inutilisé) | |
7b..8f 12x | unop vA, vB 7b : neg-int 7c : non-entier 7d : négatif long 7e : pas-long 7f : flottant négatif 80 : double négatif 81 : int-à-long 82 : int-à-flottant 83 : int-to-double 84 : long-entier 85 : long à flotter 86 : long pour doubler 87 : flottant vers int 88 : flottant à long 89 : flotter pour doubler 8a : double-int 8b : double à long 8c : double flottant 8d : entier vers octet 8e : int-to-char 8f : int-à-court | A: registre ou paire de destination (4 bits)B: registre source ou paire (4 bits) | Effectuez l'opération unaire identifiée sur le registre source, en stockant le résultat dans le registre de destination. |
90..af 23x | binop vAA, vBB, vCC 90 : complément 91 : sous-int 92 : multiint 93 : div-int 94: rem-int 95 : et-int 96 : ou-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 : et-long a1 : or-long a2 : xor-long a3 : shl-long a4 : shr-long a5 : ushr-long a6 : ajouter-flottant a7 : sous-flottant a8 : flottant multiple a9 : div-flotteur aa : rem-flotteur ab : addition-double ac : sous-double annonce : mul-double ae : div-double af : rem-double | A: registre ou paire de destination (8 bits)B: premier registre source ou paire (8 bits)C: deuxième registre source ou paire (8 bits) | Effectuez l'opération binaire identifiée sur les deux registres source, en stockant le résultat dans le registre de destination. Remarque : Contrairement aux autres opérations mathématiques |
b0..cf 12x | binop /2addr vA, vB b0 : add-int/2addr b1 : sous-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 : ajouter-flottant/2addr c7 : sous-flottant/2addr c8 : mul-flottant/2addr c9 : div-float/2addr ca: rem-float/2addr cb : ajouter-double/2addr cc : sous-double/2addr cd : mul-double/2addr ce : div-double/2addr cf: rem-double/2addr | A: registre ou paire de destination et de première source (4 bits)B: deuxième registre source ou paire (4 bits) | Effectuez l'opération binaire identifiée sur les deux registres source, en stockant le résultat dans le premier registre source. Remarque : Contrairement aux autres opérations mathématiques |
d0..d7 22s | binop /lit16 vA, vB, #+CCCC d0 : add-int/lit16 d1 : rsub-int (soustraction inverse) d2 : multiint/lit16 d3 : div-int/lit16 d4 : rem-int/lit16 d5 : et-int/lit16 d6 : or-int/lit16 d7 : xor-int/lit16 | A: registre de destination (4 bits)B: registre source (4 bits)C: constante entière signée (16 bits) | Effectuez l'opération binaire indiquée sur le registre indiqué (premier argument) et la valeur littérale (deuxième argument), en stockant le résultat dans le registre de destination. Remarque : |
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: registre de destination (8 bits)B: registre source (8 bits)C: constante entière signée (8 bits) | Effectuez l'opération binaire indiquée sur le registre indiqué (premier argument) et la valeur littérale (deuxième argument), en stockant le résultat dans le registre de destination. Remarque : Voir ci-dessous pour plus de détails sur la sémantique de |
e3..f9 10x | (inutilisé) | (inutilisé) | |
fa 45cc | invoquer polymorphe {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH | A: nombre de mots d'argument (4 bits)B: indice de référence de méthode (16 bits)C: récepteur (4 bits)D..G: registres d'arguments (4 bits chacun)H: indice de référence prototype (16 bits) | Invoquez la méthode polymorphe de signature indiquée. Le résultat (le cas échéant) peut être stocké avec une variante move-result* appropriée comme instruction immédiatement suivante.La référence de méthode doit être une méthode polymorphe de signature, telle que java.lang.invoke.MethodHandle.invoke ou java.lang.invoke.MethodHandle.invokeExact .Le récepteur doit être un objet prenant en charge la méthode polymorphe de signature invoquée. La référence du prototype décrit les types d'arguments fournis et le type de retour attendu. Le bytecode d'appel invoke-polymorphic peut déclencher des exceptions lorsqu'il s'exécute. Les exceptions sont décrites dans la documentation de l'API pour la méthode polymorphe de signature invoquée.Présent dans les fichiers Dex à partir de la version 038 . |
fb 4rcc | invoquer-polymorphique/plage {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH | A: nombre de mots d'argument (8 bits)B: indice de référence de méthode (16 bits)C: récepteur (16 bits)H: indice de référence prototype (16 bits)N = A + C - 1 | Appelez le handle de méthode indiqué. Voir la description d' invoke-polymorphic ci-dessus pour plus de détails.Présent dans les fichiers Dex à partir de la version 038 . |
fc 35c | invoquer-personnalisé {vC, vD, vE, vF, vG}, call_site@BBBB | A: nombre de mots d'argument (4 bits)B: indice de référence du site d'appel (16 bits)C..G: registres d'arguments (4 bits chacun) | Résout et invoque le site d'appel indiqué. Le résultat de l'invocation (le cas échéant) peut être stocké avec une variante move-result* appropriée comme instruction immédiatement suivante.Cette instruction s'exécute en deux phases : résolution du site d'appel et invocation du site d'appel. La résolution du site d'appel vérifie si le site d'appel indiqué a une instance java.lang.invoke.CallSite associée. Si ce n'est pas le cas, la méthode de l'éditeur de liens d'amorçage pour le site d'appel indiqué est invoquée à l'aide des arguments présents dans le fichier DEX (voir call_site_item ). La méthode bootstrap linker renvoie une instance java.lang.invoke.CallSite qui sera ensuite associée au site d'appel indiqué si aucune association n'existe. Un autre thread peut avoir déjà effectué l'association en premier, et si c'est le cas, l'exécution de l'instruction se poursuit avec la première instance java.lang.invoke.CallSite associée.L'invocation du site d'appel est effectuée sur la cible java.lang.invoke.MethodHandle de l'instance java.lang.invoke.CallSite résolue. La cible est appelée comme si elle exécutait invoke-polymorphic (décrit ci-dessus) en utilisant le handle de méthode et les arguments de l'instruction invoke-custom comme arguments d'un appel de handle de méthode exact.Les exceptions déclenchées par la méthode de l'éditeur de liens bootstrap sont encapsulées dans une java.lang.BootstrapMethodError . Une BootstrapMethodError est également déclenchée si :
038 . |
fd 3rc | invoquer-personnalisé/plage {vCCCC .. vNNNN}, call_site@BBBB | A: nombre de mots d'argument (8 bits)B: indice de référence du site d'appel (16 bits)C: registre du premier argument (16 bits)N = A + C - 1 | Résoudre et invoquer un site d'appel. Voir la description d' invoke-custom ci-dessus pour plus de détails.Présent dans les fichiers Dex à partir de la version 038 . |
fe 21c | const-method-handle vAA, method_handle@BBBB | A: registre de destination (8 bits)B: indice de poignée de méthode (16 bits) | Déplace une référence au handle de méthode spécifié par l'index donné dans le registre spécifié. Présent dans les fichiers Dex à partir de la version 039 . |
ff 21c | const-method-type vAA, proto@BBBB | A: registre de destination (8 bits)B: référence du prototype de méthode (16 bits) | Déplace une référence au prototype de méthode spécifié par l'index donné dans le registre spécifié. Présent dans les fichiers Dex à partir de la version 039 . |
format de charge utile de commutateur compressé
Nom | Format | La description |
---|---|---|
identifier | ushort = 0x0100 | identifier le pseudo-opcode |
Taille | bref | nombre d'entrées dans le tableau |
first_key | entier | première (et la plus basse) valeur de cas de commutation |
cibles | int[] | liste des cibles de branche relatives à la size . Les cibles sont relatives à l'adresse de l'opcode du commutateur, pas à cette table. |
Remarque : Le nombre total d'unités de code pour une instance de cette table est de (size * 2) + 4
.
format de charge utile de commutateur clairsemé
Nom | Format | La description |
---|---|---|
identifier | ushort = 0x0200 | identifier le pseudo-opcode |
Taille | bref | nombre d'entrées dans le tableau |
clés | int[] | liste des valeurs de clé de size , triées de bas en haut |
cibles | int[] | liste des cibles de branche relatives de size , chacune correspondant à la valeur de clé au même index. Les cibles sont relatives à l'adresse de l'opcode du commutateur, pas à cette table. |
Remarque : Le nombre total d'unités de code pour une instance de cette table est de (size * 4) + 2
.
format de charge utile de données de tableau de remplissage
Nom | Format | La description |
---|---|---|
identifier | ushort = 0x0300 | identifier le pseudo-opcode |
largeur_élément | bref | nombre d'octets dans chaque élément |
Taille | uint | nombre d'éléments dans le tableau |
Les données | ubyte[] | valeurs de données |
Remarque : Le nombre total d'unités de code pour une instance de cette table est (size * element_width + 1) / 2 + 4
.
Détails des opérations mathématiques
Remarque : Les opérations en virgule flottante doivent suivre les règles IEEE 754, en utilisant l'arrondi au plus proche et le sous-dépassement progressif, sauf indication contraire.
Code d'opération | C Sémantique | Remarques |
---|---|---|
neg-int | int32a; int32 résultat = -a ; | Complément à deux unaire. |
non-entier | int32a; int32 result = ~a; | Complément à un unaire. |
négatif long | int64a; int64 résultat = -a ; | Complément à deux unaire. |
pas longtemps | int64a; int64 result = ~a; | Complément à un unaire. |
flotteur négatif | flotter un ; float result = -a; | Floating point negation. |
neg-double | double a; double result = -a; | Floating point negation. |
int-to-long | int32 a; int64 result = (int64) a; | Sign extension of int32 into int64 . |
int-to-float | int32 a; float result = (float) a; | Conversion of int32 to float , using round-to-nearest. This loses precision for some values. |
int-to-double | int32 a; double result = (double) a; | Conversion of int32 to double . |
long-to-int | int64 a; int32 result = (int32) a; | Truncation of int64 into int32 . |
long-to-float | int64 a; float result = (float) a; | Conversion of int64 to float , using round-to-nearest. This loses precision for some values. |
long-to-double | int64 a; double result = (double) a; | Conversion of int64 to double , using round-to-nearest. This loses precision for some values. |
float-to-int | float a; int32 result = (int32) a; | Conversion of float to int32 , using round-toward-zero. NaN and -0.0 (negative zero) convert to the integer 0 . Infinities and values with too large a magnitude to be represented get converted to either 0x7fffffff or -0x80000000 depending on sign. |
float-to-long | float a; int64 result = (int64) a; | Conversion of float to int64 , using round-toward-zero. The same special case rules as for float-to-int apply here, except that out-of-range values get converted to either 0x7fffffffffffffff or -0x8000000000000000 depending on sign. |
float-to-double | float a; double result = (double) a; | Conversion of float to double , preserving the value exactly. |
double-to-int | double a; int32 result = (int32) a; | Conversion of double to int32 , using round-toward-zero. The same special case rules as for float-to-int apply here. |
double-to-long | double a; int64 result = (int64) a; | Conversion of double to int64 , using round-toward-zero. The same special case rules as for float-to-long apply here. |
double-to-float | double a; float result = (float) a; | Conversion of double to float , using round-to-nearest. This loses precision for some values. |
int-to-byte | int32 a; int32 result = (a << 24) >> 24; | Truncation of int32 to int8 , sign extending the result. |
int-to-char | int32 a; int32 result = a & 0xffff; | Truncation of int32 to uint16 , without sign extension. |
int-to-short | int32 a; int32 result = (a << 16) >> 16; | Truncation of int32 to int16 , sign extending the result. |
add-int | int32 a, b; int32 result = a + b; | Twos-complement addition. |
sub-int | int32 a, b; int32 result = a - b; | Twos-complement subtraction. |
rsub-int | int32 a, b; int32 result = b - a; | Twos-complement reverse subtraction. |
mul-int | int32 a, b; int32 result = a * b; | Twos-complement multiplication. |
div-int | int32 a, b; int32 result = a / b; | Twos-complement division, rounded towards zero (that is, truncated to integer). This throws ArithmeticException if b == 0 . |
rem-int | int32 a, b; int32 result = a % b; | Twos-complement remainder after division. The sign of the result is the same as that of a , and it is more precisely defined as result == a - (a / b) * b . This throws ArithmeticException if b == 0 . |
and-int | int32 a, b; int32 result = a & b; | Bitwise AND. |
or-int | int32 a, b; int32 result = a | b; | Bitwise OR. |
xor-int | int32 a, b; int32 result = a ^ b; | Bitwise XOR. |
shl-int | int32 a, b; int32 result = a << (b & 0x1f); | Bitwise shift left (with masked argument). |
shr-int | int32 a, b; int32 result = a >> (b & 0x1f); | Bitwise signed shift right (with masked argument). |
ushr-int | uint32 a, b; int32 result = a >> (b & 0x1f); | Bitwise unsigned shift right (with masked argument). |
add-long | int64 a, b; int64 result = a + b; | Twos-complement addition. |
sub-long | int64 a, b; int64 result = a - b; | Twos-complement subtraction. |
mul-long | int64 a, b; int64 result = a * b; | Twos-complement multiplication. |
div-long | int64 a, b; int64 result = a / b; | Twos-complement division, rounded towards zero (that is, truncated to integer). This throws ArithmeticException if b == 0 . |
rem-long | int64 a, b; int64 result = a % b; | Twos-complement remainder after division. The sign of the result is the same as that of a , and it is more precisely defined as result == a - (a / b) * b . This throws ArithmeticException if b == 0 . |
and-long | int64 a, b; int64 result = a & b; | Bitwise AND. |
or-long | int64 a, b; int64 result = a | b; | Bitwise OR. |
xor-long | int64 a, b; int64 result = a ^ b; | Bitwise XOR. |
shl-long | int64 a; int32 b; int64 result = a << (b & 0x3f); | Bitwise shift left (with masked argument). |
shr-long | int64 a; int32 b; int64 result = a >> (b & 0x3f); | Bitwise signed shift right (with masked argument). |
ushr-long | uint64 a; int32 b; int64 result = a >> (b & 0x3f); | Bitwise unsigned shift right (with masked argument). |
add-float | float a, b; float result = a + b; | Floating point addition. |
sub-float | float a, b; float result = a - b; | Floating point subtraction. |
mul-float | float a, b; float result = a * b; | Floating point multiplication. |
div-float | float a, b; float result = a / b; | Floating point division. |
rem-float | float a, b; float result = a % b; | Floating point remainder after division. This function is different than IEEE 754 remainder and is defined as result == a - roundTowardZero(a / b) * b . |
add-double | double a, b; double result = a + b; | Floating point addition. |
sub-double | double a, b; double result = a - b; | Floating point subtraction. |
mul-double | double a, b; double result = a * b; | Floating point multiplication. |
div-double | double a, b; double result = a / b; | Floating point division. |
rem-double | double a, b; double result = a % b; | Floating point remainder after division. This function is different than IEEE 754 remainder and is defined as result == a - roundTowardZero(a / b) * b . |