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 des registres, et la taille des frames est fixe lors de leur création.
Chaque frame se compose d'un nombre particulier de registres (spécifiés par la méthode) ainsi que de toutes les données supplémentaires nécessaires à l'exécution de la méthode, telles que (mais sans s'y limiter) le compteur de programme et une référence au fichier
.dex
contenant la méthode. - Lorsqu'ils sont utilisés pour des valeurs de bits (telles que des 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 de 64 bits. Aucune exigence d'alignement n'est requise pour les paires de registres.
- Lorsqu'ils sont utilisés pour les références d'objets, les registres sont considérés comme suffisamment larges pour contenir exactement une seule référence de ce type.
- En termes de représentation par bits,
(Object) null == (int) 0
. - Les N arguments d'une méthode se trouvent dans les derniers N registres du frame d'appel 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 des registres, et la taille des frames est fixe lors de leur création.
Chaque frame se compose d'un nombre particulier de registres (spécifiés par la méthode) ainsi que de toutes les données supplémentaires nécessaires à l'exécution de 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 du flux d'instructions est une quantité de 16 bits non signée. Certains bits de certaines instructions sont ignorés ou doivent être nuls.
- Les instructions ne sont pas limitées à un type particulier. Par exemple, les instructions qui déplacent des valeurs de registre 32 bits sans interprétation n'ont pas besoin de spécifier si elles déplacent des entiers ou des nombres à virgule flottante.
- Il existe des pools de constantes énumérés et indexés séparément pour les références aux chaînes, types, champs et méthodes.
- Les données littérales binaires sont représentées en ligne dans le flux d'instructions.
- En pratique, il est rare qu'une méthode ait besoin de plus de 16 registres, et il est assez courant d'en avoir besoin de plus de huit. Par conséquent, de nombreuses instructions ne s'adressent qu'aux 16 premiers registres. Lorsque cela est raisonnablement possible, les instructions autorisent des références jusqu'aux 256 premiers registres. De plus, certaines instructions comportent des variantes qui permettent de compter un nombre de registres beaucoup plus important, y compris une paire d'instructions
move
génériques pouvant adresser des registres dans la plagev0
àv65535
. Dans les cas où une variante d'instruction n'est pas disponible pour adresser un registre souhaité, le contenu du registre doit être déplacé du registre d'origine vers un registre bas (avant l'opération) et/ou d'un registre de résultat bas vers un registre haut (après l'opération). - Plusieurs "pseudo-instructions" sont utilisées pour contenir des charges utiles de données à longueur variable, auxquelles font référence des instructions régulières (par exemple,
fill-array-data
). De telles instructions ne doivent jamais être rencontrées lors du flux d'exécution normal. De plus, les instructions doivent se trouver sur des décalages de code octet pairs (c'est-à-dire alignés sur quatre octets). Pour 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 ne serait pas alignée. Enfin, bien que cela ne soit pas obligatoire, la plupart des outils devraient choisir d'émettre ces instructions à la fin des méthodes, car il serait autrement 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, ce qui modifie leur format, en tant qu'optimisation de la liaison statique au moment de l'installation. Cela permet d'accélérer l'exécution une fois la liaison connue. Consultez le document sur les formats d'instructions associé pour connaître les variantes suggérées. Le mot "suggérées" est utilisé à dessein. Il n'est pas obligatoire de les implémenter.
- Syntaxe et mnémoniques adaptées aux humains :
- Ordre de destination, puis de source pour les arguments.
- Certains opcodes comportent un suffixe de nom permettant de les distinguer 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 suivis du suffixe
-wide
. - Les opcodes spécifiques au type sont suivis d'un suffixe correspondant à leur type (ou à une abréviation simple), parmi les suivants:
-boolean
,-byte
,-char
,-short
,-int
,-long
,-float
,-double
,-object
,-string
,-class
et-void
.
- Certains opcodes comportent un suffixe permettant de distinguer des opérations identiques qui présentent des mises en page ou des options d'instruction différentes. Ces suffixes sont séparés des noms principaux par une barre oblique ("
/
") et existent principalement pour établir une mise en correspondance individuelle 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 ci-dessous, la largeur d'une valeur (indiquant, par exemple, la plage d'une constante ou le nombre de registres pouvant être adressés) est mise en évidence par l'utilisation d'un caractère pour quatre bits de largeur.
- Par exemple, dans l'instruction "
move-wide/from16 vAA, vBBBB
" :- "
move
" est l'opcode de base, qui indique l'opération de base (déplacer la valeur d'un registre). - "
wide
" est le suffixe de nom, qui indique qu'il fonctionne sur des données larges (64 bits). - "
from16
" est le suffixe d'instruction, qui indique une variante dont la source est une référence de registre 16 bits. - "
vAA
" est le registre de destination (impliqué par l'opération. Encore une fois, la règle est que les arguments de destination viennent toujours en premier), qui doit se trouver dans la plagev0
àv255
. - "
vBBBB
" est le registre source, qui doit se trouver dans la plagev0
àv65535
.
- "
- Pour en savoir plus sur les différents formats d'instructions (listés sous "Op & Format"), ainsi que sur la syntaxe de l'opcode, consultez le document sur les formats d'instructions.
- Pour en savoir plus sur l'emplacement du bytecode dans l'ensemble, consultez la documentation sur le format de fichier
.dex
.
Résumé de l'ensemble de bytecode
Opération et format | Mnémonique / Syntaxe | Arguments | Description |
---|---|---|---|
00 10x | nop | Cycles des déchets.
Remarque:Les pseudo-instructions contenant des données sont taguées avec cet opcode, auquel cas l'octet de poids fort de l'unité d'opcode indique la nature des données. Consultez les sections "Format |
|
01 12x | move vA, vB | Registre de destination A: (4 bits)Registre de source B: (4 bits) |
Déplacer le contenu d'un registre non objet vers un autre |
02 22x | move/from16 vAA, vBBBB | Registre de destination A: (8 bits)Registre source B: (16 bits) |
Déplacer le contenu d'un registre non objet vers un autre |
03 32x | move/16 vAAAA, vBBBB | Registre de destination A: (16 bits)Registre source B: (16 bits) |
Déplacer le contenu d'un registre non objet vers un autre |
04 12x | move-wide vA, vB | A: Paire de registres de destination (4 bits)B: Paire de registres de 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 | move-wide/from16 vAA, vBBBB | A: Paire de registres de destination (8 bits)B: Paire de registres de 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 | move-wide/16 vAAAA, vBBBB | Paire de registres de destination A: (16 bits)Paire de registres de source B: (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 | move-object vA, vB | Registre de destination A: (4 bits)Registre de source B: (4 bits) |
Déplacer le contenu d'un registre contenant des objets vers un autre |
08 22x | move-object/from16 vAA, vBBBB | Registre de destination A: (8 bits)Registre source B: (16 bits) |
Déplacer le contenu d'un registre contenant des objets vers un autre |
09 32x | move-object/16 vAAAA, vBBBB | Registre de destination A: (16 bits)Registre source B: (16 bits) |
Déplacer le contenu d'un registre contenant des objets vers un autre |
0a 11x | vAA move-result | Registre de destination A: (8 bits) |
Déplacez le résultat non objet à un seul mot de la invoke-kind la plus récente dans le registre indiqué.
Cela doit être fait en tant qu'instruction immédiatement après un invoke-kind dont le résultat (mot unique, non objet) ne doit pas être ignoré. Tout autre emplacement est non valide. |
0b 11x | vAA move-result-wide | Paire de registres de destination A: (8 bits) |
Déplacez le résultat en double-mot de la invoke-kind la plus récente dans la paire de registres indiquée.
Cela doit être fait en tant qu'instruction immédiatement après un invoke-kind dont le résultat (double-mot) ne doit pas être ignoré. Tout autre emplacement est non valide. |
0c 11x | move-result-object vAA | Registre de destination A: (8 bits) |
Déplacez le résultat de l'objet de l'invoke-kind la plus récente dans le registre indiqué. Cela doit être fait en tant qu'instruction immédiatement après un invoke-kind ou un filled-new-array dont le résultat (objet) ne doit pas être ignoré. Tout autre emplacement est non valide. |
0 j 11x | move-exception vAA | Registre de destination A: (8 bits) |
Enregistre une exception vient d'être détectée dans le registre donné. Il doit s'agir de la première instruction de tout gestionnaire d'exception dont l'exception détectée ne doit pas être ignorée. Cette instruction ne doit jamais se produire en tant que première instruction d'un gestionnaire d'exception. Tout autre emplacement est non valide. |
0e 10x | return-void | Retour à partir d'une méthode void . |
|
0f 11x | return vAA | Registre de valeur renvoyée A: (8 bits) |
Retour à partir d'une méthode renvoyant une valeur non objet à largeur unique (32 bits). |
10 11x | vAA de retour | Paire de registres de valeur renvoyée A: (8 bits) |
Retour à partir d'une méthode renvoyant une valeur à double largeur (64 bits). |
11 11x | vAA de l'objet de retour | Registre de valeur renvoyée A: (8 bits) |
Retour d'une méthode renvoyant un objet. |
12 11n | const/4 vA, #+B | Registre de destination A: (4 bits)Entier signé B: (4 bits) |
Déplace la valeur littérale donnée (étendue à 32 bits) dans le registre spécifié. |
13 21 s | const/16 vAA, #+BBBB | Registre de destination A: (8 bits)B: entier signé (16 bits) |
Déplace la valeur littérale donnée (étendue à 32 bits) dans le registre spécifié. |
14 31i | const vAA, #+BBBBBBBB | Registre de destination A: (8 bits)B: constante arbitraire de 32 bits |
Déplace la valeur littérale donnée dans le registre spécifié. |
15 21h | const/high16 vAA, #+BBBB0000 | Registre de destination A: (8 bits)B: entier signé (16 bits) |
Déplace la valeur littérale donnée (étendue à 32 bits à droite) dans le registre spécifié. |
16 21 | const-wide/16 vAA, #+BBBB | Registre de destination A: (8 bits)B: entier signé (16 bits) |
Déplace la valeur littérale donnée (étendue à 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éplace la valeur littérale donnée (étendue à 64 bits) dans la paire de registres spécifiée. |
18 51 l | vAA de portée globale, #+BBBBBBBBBBBBBBBB | A: Registre de destination (8 bits)B: Constante arbitraire à double largeur (64 bits) |
Déplace la valeur littérale donnée dans la paire de registres spécifiée. |
19 21h | const-wide/high16 vAA, #+BBBB000000000000 | Registre de destination A: (8 bits)B: entier signé (16 bits) |
Déplace la valeur littérale donnée (étendue à 64 bits à droite) dans la paire de registres spécifiée. |
1a 21c | const-string vAA, string@BBBB | Registre de destination A: (8 bits)Index de chaîne B: |
Déplace une référence à la chaîne spécifiée par l'index donné dans le registre spécifié. |
1b 31c | const-string/jumbo vAA, string@BBBBBBBB | Registre de destination A: (8 bits)Index de chaîne B: |
Déplace une référence à la chaîne spécifiée par l'index donné dans le registre spécifié. |
1c 21c | const-class vAA, type@BBBB | Registre de destination A: (8 bits)Index de type B: |
Déplacez une référence à la classe spécifiée par l'index donné dans le registre spécifié. Si le type indiqué est primitif, une référence à la classe dégénérée du type primitif est stockée. |
1d 11x | monitor-enter vAA | Registre de référence A: (8 bits) |
Acquérir le moniteur pour l'objet indiqué. |
1e 11x | monitor-exit vAA | Registre de référence A: (8 bits) |
Libérez le moniteur pour l'objet indiqué.
Remarque:Si cette instruction doit générer une exception, elle doit le faire comme si le processeur avait déjà avancé au-delà de l'instruction.
Il peut être utile de considérer que l'instruction s'exécute correctement (dans un sens) et que l'exception est générée après l'instruction, mais avant que la suivante ait la possibilité de s'exécuter. Cette définition permet à une méthode d'utiliser un nettoyeur de moniteur générique (par exemple, |
1f 21c | check-cast vAA, type@BBBB | A: registre avec référence (8 bits)B: indice de type (16 bits) |
Génère une exception ClassCastException si la référence du registre donné ne peut pas être convertie au type indiqué.
Remarque:Étant donné que |
20 22c | instance-of vA, vB, type@CCCC | Registre de destination A: (4 bits)Registre contenant une référence B: (4 bits)Index de type C: (16 bits) |
Stockez dans le registre de destination donné 1 si la référence indiquée est une instance du type donné, ou 0 si ce n'est pas le cas.
Remarque:Étant donné que |
21 12x | vA, vB (longueur de tableau) | Registre de destination A: (4 bits)Registre de référence de tableau B: (4 bits) |
Stockez dans le registre de destination donné la longueur du tableau indiqué, en entrées. |
22 21c | new-instance vAA, type@BBBB | Registre de destination A: (8 bits)Index de type B: |
Créez une instance du type indiqué, en stockant une référence à celle-ci dans la destination. Le type doit faire référence à une classe autre qu'un tableau. |
23 22c | new-array vA, vB, type@CCCC | Registre de destination A: (4 bits)Registre de taille B: Index de type C: |
Créez un tableau du type et de la taille indiqués. Le type doit être un type de tableau. |
24 35c | filled-new-array {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)
|
Construit un tableau du type et de la taille donnés, en le remplissant avec le contenu fourni. Le type doit être un type de tableau. Le contenu du tableau doit être constitué d'un seul mot (c'est-à-dire qu'il ne doit pas y avoir de tableaux de long ou de double , mais les types de référence sont acceptés). L'instance créée est stockée en tant que "résultat" de la même manière que les instructions d'appel de méthode stockent leurs résultats. L'instance créée doit donc être déplacée vers un registre avec une instruction move-result-object immédiatement suivante (si elle doit être utilisée). |
25 3rc | filled-new-array/range {vCCCC .. vNNNN}, type@BBBB | A: taille du tableau et nombre de mots d'argument (8 bits)B: indice de type (16 bits)C: registre du premier argument (16 bits)N = A + C - 1 |
Construit un tableau du type et de la taille donnés, en le remplissant avec le contenu fourni. Les clarifications et les restrictions sont identiques à celles de filled-new-array , décrites ci-dessus. |
26 31t | fill-array-data vAA, +BBBBBBBB (avec les données supplémentaires spécifiées ci-dessous dans "fill-array-data-payload Format") |
Référence de tableau A: (8 bits)Décalage signé de la "branche" vers la pseudo-instruction de données de table B: (32 bits)
|
Remplissez le tableau donné avec les données indiquées. La référence doit être un tableau de primitives, et le tableau de données doit lui correspondre en type et ne pas contenir plus d'éléments que ceux qui peuvent tenir dans le tableau. Autrement dit, le tableau peut être plus volumineux que la table. Dans ce cas, seuls les éléments initiaux du tableau sont définis, laissant le reste intact. |
27 11x | générer vAA | Registre A: contenant des exceptions (8 bits) |
Générez l'exception indiquée. |
28 10t | goto +AA | Décalage de branche signé A: (8 bits) |
Saute sans condition à l'instruction indiquée.
Remarque:Le décalage de la branche ne doit pas être |
29 20t | goto/16 +AAAA | A: Décalage de branche signé (16 bits) |
Saute sans condition à l'instruction indiquée.
Remarque:Le décalage de la branche ne doit pas être |
2a 30t | goto/32 +AAAAAAAA | Décalage de branche signé A: (32 bits) |
Saute sans condition à l'instruction indiquée. |
2b 31t | packed-switch vAA, +BBBBBBBB (avec les données supplémentaires spécifiées ci-dessous dans "packed-switch-payload Format") |
Registre A: pour le testDécalage de "branchement" signé B: vers la pseudo-instruction de données de table
(32 bits)
|
Saute vers une nouvelle instruction en fonction de la valeur du registre donné, à l'aide d'un tableau de décalages correspondant à chaque valeur d'une plage d'entiers particulière, ou passe à l'instruction suivante en cas de non-correspondance. |
2c 31t | sparse-switch vAA, +BBBBBBBB (avec les données supplémentaires spécifiées ci-dessous dans "sparse-switch-payload Format") |
Registre A: pour le testDécalage de "branchement" signé B: vers la pseudo-instruction de données de table
(32 bits)
|
Accédez à une nouvelle instruction en fonction de la valeur du registre donné, à l'aide d'un tableau ordonné de paires valeur-décalage, ou passez à l'instruction suivante en cas de non-correspondance. |
2d..31 23x | cmpkind vAA, vBB, vCC 2d: cmpl-float (biais inférieur) 2e: cmpg-float (biais supérieur) 2f: cmpl-double (biais inférieur) 30: cmpg-double (biais supérieur) 31: cmp-long |
A: Registre de destination (8 bits)B: Premier registre ou paire de sourceC: Deuxième registre ou paire de source |
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" indiqué pour les opérations à virgule flottante indique comment les comparaisons NaN sont traitées : les instructions "biais gt" renvoient 1 pour les comparaisons NaN , et les instructions "biais lt" renvoient -1 .
Par exemple, pour vérifier si un nombre à virgule flottante est |
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: premier registre à tester (4 bits)B: deuxième registre à tester (4 bits)C: décalage de branche signé (16 bits) |
Branchement vers la destination donnée si les valeurs des deux registres donnés sont comparées comme spécifié.
Remarque:Le décalage de la branche ne doit pas être |
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 |
Registre A: à tester (8 bits)Décalage de branche signé B: (16 bits) |
Branchement vers la destination donnée si la valeur du registre donné est comparée à 0, comme spécifié.
Remarque:Le décalage de la branche ne doit pas être |
3e..43 10x | (inutilisé) | (inutilisé) | |
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 |
Registre ou paire de valeurs A: (peut être source ou destination) (8 bits)Registre de tableau B: (8 bits)Registre d'index C: (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 valeurs. |
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 |
Registre ou paire de valeurs A: ; peut être source ou destination (4 bits)Registre d'objet B: (4 bits)Index de référence de champ d'instance C: (16 bits) |
Effectuez l'opération de champ d'instance d'objet identifiée avec le champ identifié, en le chargeant ou en le stockant dans le registre de valeurs.
Remarque:Ces opcodes sont des candidats raisonnables pour le lien statique, en modifiant l'argument de champ pour qu'il soit un décalage plus direct. |
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 |
Registre ou paire de valeurs A: . Peut être source ou destination (8 bits)Index de référence de champ statique B: (16 bits) |
Effectuez l'opération de champ statique de l'objet identifié avec le champ statique identifié, en le chargeant ou en le stockant dans le registre de valeurs.
Remarque:Ces opcodes sont des candidats raisonnables pour le lien statique, en modifiant l'argument de champ pour qu'il soit un décalage plus direct. |
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 |
Nombre de mots d'argument A: (4 bits)Index de référence de méthode B: (16 bits)Registres d'argument C..G: (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 Dans les fichiers DEX version
Remarque:Ces opcodes sont des candidats raisonnables pour le lien statique, en modifiant l'argument de la méthode pour qu'il soit un décalage plus direct (ou une paire de celui-ci). |
73 10x | (inutilisé) | (inutilisé) | |
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: Nombre de mots d'argument (8 bits)B: Indice de référence de la méthode (16 bits)C: Registre du premier argument (16 bits)N = A + C - 1 |
Appelez la méthode indiquée. Pour en savoir plus, consulter la première description de invoke-kind ci-dessus.
|
79..7a 10x | (inutilisé) | (inutilisé) | |
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: registre ou paire de destination (4 bits)B: registre ou paire de source (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: 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: Paire ou registre de destination (8 bits)B: Paire ou registre de première source (8 bits)C: Paire ou registre de deuxième source (8 bits) |
Effectuez l'opération binaire identifiée sur les deux registres sources, 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: 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: Destination et premier registre ou paire source (4 bits)B: Deuxième registre ou paire source (4 bits) |
Effectuez l'opération binaire identifiée sur les deux registres sources, 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: mul-int/lit16 d3: div-int/lit16 d4: rem-int/lit16 d5: and-int/lit16 d6: or-int/lit16 d7: xor-int/lit16 |
A: registre de destination (4 bits)B: registre source (4 bits)C: constante int signée (16 bits) |
Effectue 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 |
Registre de destination A: (8 bits)Registre source B: (8 bits)Constante int signée C: (8 bits) |
Effectue 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:Pour en savoir plus sur la sémantique de |
e3..f9 10x | (inutilisé) | (inutilisé) | |
fa 45 cm³ | invoke-polymorphic {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH |
A: Nombre de mots d'argument (4 bits) B: Indice de référence de la méthode (16 bits) C: Récepteur (4 bits) D..G: Enregistreurs d'arguments (4 bits chacun) H: Indice de référence du prototype (16 bits)
|
Appelez 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 faire référence à 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 compatible avec la méthode polymorphe de signature appelée. La référence de prototype décrit les types d'arguments fournis et le type de retour attendu. Le bytecode invoke-polymorphic peut générer des exceptions lors de son exécution. Les exceptions sont décrites dans la documentation de l'API pour la méthode polymorphe de signature appelée.Présent dans les fichiers DEX à partir de la version 038 .
|
fb 4rcc | invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH |
A: Nombre de mots d'argument (8 bits) B: Indice de référence de la méthode (16 bits) C: Récepteur (16 bits) H: Indice de référence du prototype (16 bits) N = A + C - 1
|
Appelez le gestionnaire de méthode indiqué. Pour en savoir plus, consultez la description de invoke-polymorphic ci-dessus.Présent dans les fichiers DEX à partir de la version 038 .
|
fc 35c | invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB |
Nombre de mots d'argument A: (4 bits) Index de référence du site d'appel B: (16 bits) Registres d'argument C..G: (4 bits chacun)
|
Résout et appelle le site d'appel indiqué.
Le résultat de l'appel (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 appel du site d'appel. La résolution du site d'appel vérifie si le site d'appel indiqué est associé à une instance java.lang.invoke.CallSite .
Dans le cas contraire, la méthode de l'éditeur de liens de démarrage pour le site d'appel indiqué est appelée à l'aide des arguments présents dans le fichier DEX (voir call_site_item). La méthode de l'éditeur de liens de démarrage renvoie une instance java.lang.invoke.CallSite qui sera ensuite associée au site d'appel indiqué si aucune association n'existe. Il est possible qu'un autre thread ait déjà effectué l'association en premier. Dans ce cas, l'exécution de l'instruction se poursuit avec la première instance java.lang.invoke.CallSite associée.L'appel du site est effectué 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) à l'aide du gestionnaire de méthode et des arguments de l'instruction invoke-custom comme arguments d'une invocation de gestionnaire de méthode exacte.Les exceptions générées par la méthode de l'éditeur de liens de démarrage sont encapsulées dans un java.lang.BootstrapMethodError . Une BootstrapMethodError est également générée dans les cas suivants :
038 .
|
fd 3rc | invoke-custom/range {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ésolvez et appelez un site d'appel. Pour en savoir plus, consultez la description de invoke-custom ci-dessus.Présent dans les fichiers DEX à partir de la version 038 .
|
fe 21c | const-method-handle vAA, method_handle@BBBB | Registre de destination A: (8 bits)Index de poignée de méthode B: (16 bits) |
Déplacez une référence au gestionnaire 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 | Registre de destination A: (8 bits)Référence du prototype de méthode B: (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 packed-switch-payload
Nom | Format | Description |
---|---|---|
ident | ushort = 0x0100 | identification du pseudo-opcode |
taille | ushort | nombre d'entrées dans le tableau ; |
first_key | int | première (et plus basse) valeur de l'instruction switch |
cibles | int[] | liste des cibles de branche relatives size . Les cibles sont relatives à l'adresse de l'opcode de commutateur, et non à celle de ce tableau.
|
Remarque:Le nombre total d'unités de code pour une instance de ce tableau est (size * 2) + 4
.
Format sparse-switch-payload
Nom | Format | Description |
---|---|---|
ident | ushort = 0x0200 | identification du pseudo-opcode |
taille | ushort | nombre d'entrées dans le tableau ; |
clés | int[] | liste des valeurs de clé size , triées de la valeur la plus basse à la plus élevée |
cibles | int[] | Liste des cibles de branche relatives size , chacune correspondant à la valeur de clé au même indice. Les cibles sont relatives à l'adresse de l'opcode de commutateur, et non à celle de ce tableau.
|
Remarque:Le nombre total d'unités de code pour une instance de ce tableau est (size * 4) + 2
.
Format de la charge utile de données de remplissage d'un tableau
Nom | Format | Description |
---|---|---|
ident | ushort = 0x0300 | identification du pseudo-opcode |
element_width | ushort | Nombre d'octets dans chaque élément |
taille | uint | nombre d'éléments dans la table ; |
de données | ubyte[] | valeurs des données |
Remarque:Le nombre total d'unités de code pour une instance de ce tableau est (size * element_width + 1) / 2 + 4
.
Détails de l'opération mathématique
Remarque:Les opérations à virgule flottante doivent respecter les règles IEEE 754, en utilisant l'arrondi à la valeur la plus proche et le sous-dépassement progressif, sauf indication contraire.
Code opération | Sémantique C | Notes |
---|---|---|
neg-int | int32 a; int32 result = -a; |
Complément à deux unaire. |
not-int | int32 a; int32 result = ~a; |
Complément à unaire |
neg-long | int64 a; int64 result = -a; |
Complément à deux unaire. |
not-long | int64 a; int64 result = ~a; |
Complément à un. |
neg-float | float a; float result = -a; |
Négation à virgule flottante. |
neg-double | double a; double résultat = -a; |
Négation à virgule flottante. |
int-to-long | int32 a; int64 result = (int64) a; |
Signature de l'extension de int32 dans int64 . |
int-to-float | int32 a; float result = (float) a; |
Conversion de int32 en float , avec arrondi à la valeur la plus proche. Cela entraîne une perte de précision pour certaines valeurs.
|
int-to-double | int32 a; double résultat = (double) a; |
Conversion de int32 en double . |
long-to-int | int64 a; int32 result = (int32) a; |
Troncature de int64 en int32 . |
long-to-float | int64 a; float result = (float) a; |
Conversion de int64 en float , avec arrondi à la valeur la plus proche. Cela entraîne une perte de précision pour certaines valeurs.
|
long-to-double | int64 a; double résultat = (double) a; |
Conversion de int64 en double , avec arrondi à la valeur la plus proche. Cela entraîne une perte de précision pour certaines valeurs.
|
float-to-int | float a; int32 result = (int32) a; |
Conversion de float en int32 , à l'aide de la méthode d'arrondi à zéro. NaN et -0.0 (zéro négatif) sont convertis en entier 0 . Les valeurs infinies et celles dont la magnitude est trop élevée pour être représentées sont converties en 0x7fffffff ou -0x80000000 , selon le signe.
|
float-to-long | float a; int64 result = (int64) a; |
Conversion de float en int64 , à l'aide de la méthode d'arrondi à zéro. Les mêmes règles de cas particulier que pour float-to-int s'appliquent ici, sauf que les valeurs hors plage sont converties en 0x7fffffffffffffff ou -0x8000000000000000 en fonction du signe.
|
float-to-double | float a; double result = (double) a; |
Conversion de float en double , en conservant exactement la valeur.
|
double-to-int | double a; int32 result = (int32) a; |
Conversion de double en int32 , à l'aide de la méthode d'arrondi à zéro. Les mêmes règles de cas particulier que pour float-to-int s'appliquent ici.
|
double-to-long | double a; int64 result = (int64) a; |
Conversion de double en int64 , à l'aide de la méthode d'arrondi à zéro. Les mêmes règles de cas particulier que pour float-to-long s'appliquent ici.
|
double-to-float | double a; float result = (float) a; |
Conversion de double en float , avec arrondi à la valeur la plus proche. Cela entraîne une perte de précision pour certaines valeurs.
|
int-to-byte | int32 a; int32 résultat = (a << 24) >> 24; |
Troncature de int32 à int8 , signe prolongeant le résultat.
|
int-to-char | int32 a; int32 résultat = a & 0xffff; |
Troncature de int32 à uint16 , sans extension du signe.
|
int-to-short | int32 a; int32 résultat = (a << 16) >> 16; |
Troncature de int32 à int16 , signe prolongeant le résultat.
|
add-int | int32 a, b; int32 résultat = a + b; |
Addition en complément à deux. |
sous-entier | int32 a, b; int32 résultat = a - b; |
Soustraction en complément à deux |
rsub-int | int32 a, b; int32 result = b - a; |
Soustraction inverse en complément à deux |
mul-int | int32 a, b; int32 résultat = a * b; |
Multiplication en complément à deux |
div-int | int32 a, b; int32 résultat = a / b; |
Division en complément à deux, arrondie vers zéro (c'est-à-dire tronquée pour afficher un entier). Cela génère une exception ArithmeticException si b == 0 .
|
rem-int | int32 a, b; int32 résultat = a % b; |
Reste en complément à deux après division. Le signe du résultat est le même que celui de a et est défini plus précisément comme result == a - (a / b) * b . Cette opération génère une exception ArithmeticException si b == 0 .
|
and-int | int32 a, b; int32 result = a & b; |
Opérateur AND (ET) au niveau du bit. |
or-int | int32 a, b; int32 result = a | b; |
Opérateur OR au niveau du bit. |
xor-int | int32 a, b; int32 result = a ^ b; |
Opérateur XOR (OU exclusif) bit à bit. |
shl-int | int32 a, b; int32 result = a << (b & 0x1f); |
Décalage à gauche bit à bit (avec argument masqué). |
shr-int | int32 a, b; int32 result = a >> (b & 0x1f); |
Décalage à droite signé bit à bit (avec argument masqué). |
ushr-int | uint32 a, b; int32 result = a >> (b & 0x1f); |
Décalage à droite non signé bit à bit (avec argument masqué). |
add-long | int64 a, b; int64 result = a + b; |
Addition en complément à deux. |
sous-longueur | int64 a, b; int64 result = a - b; |
Soustraction en complément à deux |
mul-long | int64 a, b; int64 result = a * b; |
Multiplication en complément à deux |
div-long | int64 a, b; int64 result = a / b; |
Division en complément à deux, arrondie vers zéro (c'est-à-dire tronquée pour afficher un entier). Cela génère une exception ArithmeticException si b == 0 .
|
rem-long | int64 a, b; int64 result = a % b; |
Reste en complément à deux après division. Le signe du résultat est le même que celui de a et est défini plus précisément comme result == a - (a / b) * b . Cette opération génère une exception ArithmeticException si b == 0 .
|
and-long | int64 a, b; int64 result = a & b; |
Opérateur AND (ET) au niveau du bit. |
or-long | int64 a, b; int64 result = a | b; |
Opérateur OR au niveau du bit. |
xor-long | int64 a, b; int64 result = a ^ b; |
Opérateur XOR (OU exclusif) au niveau du bit. |
shl-long | int64 a; int32 b; int64 result = a << (b & 0x3f); |
Décalage à gauche bit à bit (avec argument masqué). |
shr-long | int64 a; int32 b; int64 result = a >> (b & 0x3f); |
Décalage à droite signé bit à bit (avec argument masqué). |
ushr-long | uint64 a; int32 b; int64 result = a >> (b & 0x3f); |
Décalage à droite non signé bit à bit (avec argument masqué). |
add-float | float a, b; float result = a + b; |
Addition à virgule flottante. |
sous-flottaison | float a, b; float result = a - b; |
Soustraction à virgule flottante. |
mul-float | float a, b; float result = a * b; |
Multiplication à virgule flottante. |
div-float | float a, b; float result = a / b; |
Division à virgule flottante. |
rem-float | float a, b; float result = a % b; |
Reste à virgule flottante après division. Cette fonction est différente du reste IEEE 754 et est définie comme result == a - roundTowardZero(a / b) * b .
|
add-double | double a, b; double résultat = a + b; |
Addition à virgule flottante. |
sous-double | double a, b; double résultat = a - b; |
Soustraction à virgule flottante. |
mul-double | double a, b; double résultat = a * b; |
Multiplication à virgule flottante. |
div-double | double a, b; double résultat = a / b; |
Division à virgule flottante. |
rem-double | double a, b; double résultat = a % b; |
Reste à virgule flottante après division. Cette fonction est différente du reste IEEE 754 et est définie comme result == a - roundTowardZero(a / b) * b .
|