Formato bytecode Dalvik

Design generale

  • Il modello di macchina e le convenzioni di chiamata hanno lo scopo di imitare approssimativamente le architetture reali comuni e le convenzioni di chiamata in stile C:
    • La macchina è basata su registri e le dimensioni dei frame sono fisse al momento della creazione. Ogni frame è costituito da un determinato numero di registri (specificati dal metodo) e da eventuali dati aggiuntivi necessari per l'esecuzione del metodo, come (a titolo esemplificativo) il contatore del programma e un riferimento al file .dex contenente il metodo.
    • Se utilizzati per valori in bit (ad esempio numeri interi e in virgola mobile), i registri sono considerati di 32 bit. Per i valori a 64 bit vengono utilizzate coppie di registri adiacenti. Non è richiesto alcun requisito di allineamento per le coppie di registri.
    • Se utilizzati per i riferimenti agli oggetti, i registri sono considerati sufficientemente ampi per contenere esattamente un riferimento di questo tipo.
    • In termini di rappresentazione a bit, (Object) null == (int) 0.
    • Gli N argomenti di un metodo vengono inseriti nell'ordine negli ultimi N registri del frame di chiamata del metodo. Gli argomenti ampi occupano due registri. Ai metodi di istanza viene passato un riferimento this come primo argomento.
  • L'unità di archiviazione nello stream di istruzioni è una quantità non firmata di 16 bit. Alcuni bit in alcune istruzioni vengono ignorati / devono essere pari a zero.
  • Le istruzioni non sono limitate inutilmente a un determinato tipo. Ad esempio, le istruzioni che spostano i valori dei registri a 32 bit senza interpretazione non devono specificare se stanno spostando interi o valori in virgola mobile.
  • Esistono pool di costanti enumerati e indicizzati separatamente per i riferimenti a stringhe, tipi, campi e metodi.
  • I dati letterali a livello di bit sono rappresentati in linea nello stream di istruzioni.
  • Poiché, in pratica, è raro che un metodo abbia bisogno di più di 16 registri e poiché la necessità di più di otto registri è ragionevolmente comune, molte istruzioni sono limitate all'indirizzamento solo dei primi 16 registri. Ove ragionevolmente possibile, le istruzioni consentono di fare riferimento fino ai primi 256 registri. Inoltre, alcune istruzioni hanno varianti che consentono conteggi di registri molto più grandi, inclusa una coppia di istruzioni move generiche che possono indirizzare i registri nell'intervallo v0-v65535. Nei casi in cui non sia disponibile una variante di istruzione per indirizzare un registro desiderato, è previsto che i contenuti del registro vengano spostati dal registro originale a un registro basso (prima dell'operazione) e/o da un registro del risultato basso a un registro alto (dopo l'operazione).
  • Esistono diverse "pseudo-istruzioni" utilizzate per memorizzare payload di dati di lunghezza variabile, a cui fanno riferimento le istruzioni regolari (ad esempio fill-array-data). Queste istruzioni non devono mai essere incontrate durante il normale flusso di esecuzione. Inoltre, le istruzioni devono trovarsi su offset del bytecode con numeri pari (ovvero allineati a 4 byte). Per soddisfare questo requisito, gli strumenti di generazione di dex devono emettere un'istruzione nop aggiuntiva come separatore se questa istruzione non fosse allineata. Infine, anche se non è obbligatorio, è previsto che la maggior parte degli strumenti scelga di emettere queste istruzioni alla fine dei metodi, poiché in caso contrario è probabile che siano necessarie istruzioni aggiuntive per eseguire il branching.
  • Quando vengono installate su un sistema in esecuzione, alcune istruzioni potrebbero essere alterate, cambiandone il formato, come ottimizzazione del collegamento statico in fase di installazione. In questo modo, l'esecuzione sarà più rapida una volta noto il collegamento. Consulta il documento relativo ai formati didattici associato per le varianti suggerite. La parola "suggerito" è usata con cautela; non è obbligatorio implementarli.
  • Sintassi e mnemoni simili a quelle umane:
    • Ordine destinazione-poi-origine per gli argomenti.
    • Alcuni opcode hanno un suffisso del nome per distinguere i tipi su cui operano:
      • Le opzioni di codice di 32 bit di tipo generale non sono contrassegnate.
      • Le opzioni di codice a 64 bit di tipo generico hanno il suffisso -wide.
      • Le opzioni di codice macchina specifiche per tipo sono seguite dal loro tipo (o da un'abbreviazione semplice), uno dei seguenti: -boolean -byte -char -short -int -long -float -double -object -string -class -void.
    • Alcuni opcode hanno un suffisso per distinguere operazioni apparentemente identiche che hanno layout o opzioni di istruzioni diversi. Questi suffissi sono separati dai nomi principali da una barra diagonale ("/") ed esistono principalmente per creare un mappatura uno a uno con costanti statiche nel codice che genera e interpreta gli eseguibili (ovvero per ridurre l'ambiguità per le persone).
    • Nelle descrizioni riportate di seguito, la larghezza di un valore (che indica, ad esempio, l'intervallo di una costante o il numero di registri eventualmente indirizzati) è evidenziata dall'uso di un carattere per quattro bit di larghezza.
    • Ad esempio, nell'istruzione "move-wide/from16 vAA, vBBBB":
      • "move" è l'opcode di base, che indica l'operazione di base (sposta il valore di un registro).
      • "wide" è il suffisso del nome, che indica che opera su dati ampi (64 bit).
      • "from16" è il suffisso dell'opcode, che indica una variante che ha un riferimento a un registro a 16 bit come origine.
      • "vAA" è il registro di destinazione (implicito nell'operazione; di nuovo, la regola è che gli argomenti di destinazione vengono sempre prima), che deve essere compreso nell'intervallo v0-v255.
      • "vBBBB" è il registro di origine, che deve rientrare nell'intervallo v0-v65535.
  • Consulta il documento relativo ai formati delle istruzioni per ulteriori dettagli sui vari formati delle istruzioni (elencati in "Op & Format") e sulla sintassi dell'opcode.
  • Per ulteriori dettagli su dove si inserisce il bytecode nel quadro più ampio, consulta il documento sul formato del file .dex.

Riepilogo dell'insieme di bytecode

Op & Format Mnemonico / sintassi Argomenti Descrizione
00 10x nop   Cicli di rifiuti.

Nota: le pseudo-istruzioni contenenti dati sono contrassegnate con questo codice operativo, nel qual caso il byte di ordine superiore dell'unità di codice operativo indica la natura dei dati. Consulta le sezioni "Formato packed-switch-payload", "Formato sparse-switch-payload" e "Formato fill-array-data-payload" di seguito.

01 12x move vA, vB A: registro di destinazione (4 bit)
B: registro di origine (4 bit)
Sposta i contenuti di un registro non oggetto in un altro.
02 22x move/from16 vAA, vBBBB A: registro di destinazione (8 bit)
B: registro di origine (16 bit)
Sposta i contenuti di un registro non oggetto in un altro.
03 32x move/16 vAAAA, vBBBB A: registro di destinazione (16 bit)
B: registro di origine (16 bit)
Sposta i contenuti di un registro non oggetto in un altro.
04 12x move-wide vA, vB A: coppia di registri di destinazione (4 bit)
B: coppia di registri di origine (4 bit)
Sposta i contenuti di una coppia di registri in un'altra.

Nota: è consentito passare da vN a vN-1 o vN+1, pertanto le implementazioni devono prevedere la lettura di entrambe le metà di una coppia di registri prima di scrivere qualsiasi cosa.

05 22x move-wide/from16 vAA, vBBBB A: Coppia di registri di destinazione (8 bit)
B: Coppia di registri di origine (16 bit)
Sposta i contenuti di una coppia di registri in un'altra.

Nota: le considerazioni sull'implementazione sono le stesse di move-wide, sopra.

06 32x move-wide/16 vAAAA, vBBBB A: Coppia di registri di destinazione (16 bit)
B: Coppia di registri di origine (16 bit)
Sposta i contenuti di una coppia di registri in un'altra.

Nota: le considerazioni sull'implementazione sono le stesse di move-wide, sopra.

07 12x move-object vA, vB A: registro di destinazione (4 bit)
B: registro di origine (4 bit)
Sposta i contenuti di un registro contenente oggetti in un altro.
08 22x move-object/from16 vAA, vBBBB A: registro di destinazione (8 bit)
B: registro di origine (16 bit)
Sposta i contenuti di un registro contenente oggetti in un altro.
09 32x move-object/16 vAAAA, vBBBB A: registro di destinazione (16 bit)
B: registro di origine (16 bit)
Sposta i contenuti di un registro contenente oggetti in un altro.
0a 11x move-result vAA A: registro di destinazione (8 bit) Sposta il risultato non oggetto di una sola parola del invoke-kind più recente nel registro indicato. Questo deve essere fatto come istruzione immediatamente dopo un invoke-kind il cui risultato (una parola, non un oggetto) non deve essere ignorato; in qualsiasi altro punto non è valido.
0b 11x move-result-wide vAA Coppia di registri di destinazione A: (8 bit) Sposta il risultato a due parole dell'invoke-kind più recente nella coppia di registri indicata. Questa istruzione deve essere eseguita immediatamente dopo un invoke-kind il cui risultato (a due parole) non deve essere ignorato; in qualsiasi altro punto non è valida.
0c 11x move-result-object vAA A: registro di destinazione (8 bit) Sposta il risultato dell'oggetto dell'invoke-kind più recente nel registro indicato. Questa istruzione deve essere eseguita immediatamente dopo un invoke-kind o un filled-new-array il cui risultato (oggetto) non deve essere ignorato. In qualsiasi altro punto non è valida.
0d 11x move-exception vAA A: registro di destinazione (8 bit) Salva un'eccezione appena rilevata nel registro specificato. Deve essere la prima istruzione di qualsiasi gestore delle eccezioni la cui eccezione rilevata non deve essere ignorata e deve verificarsi soltanto come prima istruzione di un gestore delle eccezioni. In qualsiasi altro punto non è valida.
0 e 10 volte return-void   Torna da un metodo void.
0 di 11x return vAA Registro del valore restituito A: (8 bit) Ritorna da un metodo che restituisce un valore non oggetto di larghezza singola (32 bit).
10 11x vAA a livello di ritorno A: coppia di registri del valore restituito (8 bit) Ritorna da un metodo che restituisce un valore a doppia larghezza (64 bit).
11 11x return-object vAA Registro del valore restituito A: (8 bit) Ritorna da un metodo che restituisce un oggetto.
12 11n const/4 vA, #+B A: registro di destinazione (4 bit)
B: int firmato (4 bit)
Sposta il valore letterale specificato (con segno esteso a 32 bit) nel registro specificato.
13 21 const/16 vAA, #+BBBB A: registro di destinazione (8 bit)
B: int con segno (16 bit)
Sposta il valore della stringa specificato (con segno esteso a 32 bit) nel registro specificato.
14 31i const vAA, #+BBBBBBBB A: registro di destinazione (8 bit)
B: costante arbitraria a 32 bit
Sposta il valore letterale specificato nel registro specificato.
15 21h const/high16 vAA, #+BBBB0000 A: registro di destinazione (8 bit)
B: int con segno (16 bit)
Sposta il valore letterale specificato (esteso a 32 bit a destra con zero) nel registro specificato.
16 21 const-wide/16 vAA, #+BBBB A: registro di destinazione (8 bit)
B: int con segno (16 bit)
Sposta il valore letterale specificato (con segno esteso a 64 bit) nella coppia di registri specificata.
17 31i const-wide/32 vAA, #+BBBBBBBB A: registro di destinazione (8 bit)
B: int firmato (32 bit)
Sposta il valore letterale specificato (con segno esteso a 64 bit) nella coppia di registri specificata.
18 51l const-wide vAA, #+BBBBBBBBBBBBBBBB A: registro di destinazione (8 bit)
B: costante arbitraria a doppia larghezza (64 bit)
Sposta il valore letterale specificato nella coppia di registri specificata.
19 21h const-wide/high16 vAA, #+BBBB000000000000 A: registro di destinazione (8 bit)
B: int con segno (16 bit)
Sposta il valore letterale specificato (esteso a destra a 64 bit) nella coppia di registri specificata.
1a 21c const-string vAA, string@BBBB A: registro di destinazione (8 bit)
B: indice di stringa
Sposta un riferimento alla stringa specificata dall'indice specificato nel registro specificato.
1b 31c const-string/jumbo vAA, string@BBBBBBBB A: registro di destinazione (8 bit)
B: indice di stringa
Sposta un riferimento alla stringa specificata dall'indice specificato nel registro specificato.
1c 21c const-class vAA, type@BBBB A: registro di destinazione (8 bit)
B: indice di tipo
Sposta un riferimento alla classe specificata dall'indice specificato nel registro specificato. Se il tipo indicato è primitivo, verrà memorizzato un riferimento alla classe degenere del tipo primitivo.
1 giorno 11x monitor-enter vAA A: registro con riferimento (8 bit) Acquisisci il monitor per l'oggetto indicato.
1e 11x monitor-exit vAA A: registro con riferimento (8 bit) Rilascia il monitoraggio per l'oggetto indicato.

Nota: se questa istruzione deve generare un'eccezione, deve farlo come se il PC avesse già superato l'istruzione. Potrebbe essere utile pensare che l'istruzione venga eseguita correttamente (in un certo senso) e che l'eccezione venga lanciata dopo l'istruzione, ma prima che l'istruzione successiva abbia la possibilità di essere eseguita. Questa definizione consente a un metodo di utilizzare un valore generico per la pulizia del monitor (ad es. finally) come pulizia del monitor per il blocco stesso, per gestire le eccezioni arbitrarie che potrebbero essere lanciate a causa dell'implementazione storica di Thread.stop(), mantenendo al contempo un'igiene del monitor adeguata.

1f 21c check-cast vAA, type@BBBB A: registro di riferimento (8 bit)
B: indice di tipo (16 bit)
Lancia un ClassCastException se il riferimento nel register specificato non può essere sottoposto a conversione al tipo indicato.

Nota: poiché A deve sempre essere un riferimento (e non un valore primitivo), l'operazione non andrà a buon fine obbligatoriamente in fase di runtime (ovvero verrà generata un'eccezione) se B fa riferimento a un tipo primitivo.

20 22c instance-of vA, vB, type@CCCC A: registro di destinazione (4 bit)
B: registro di riferimento (4 bit)
C: indice di tipo (16 bit)
Memorizza nel registro di destinazione specificato 1 se il riferimento indicato è un'istanza del tipo specificato, oppure 0 in caso contrario.

Nota: poiché B deve sempre essere un riferimento (e non un valore primitivo), 0 verrà sempre memorizzato se C fa riferimento a un tipo primitivo.

21 12x array-length vA, vB A: registro di destinazione (4 bit)
B: registro contenente il riferimento all'array (4 bit)
Memorizza nel registro di destinazione specificato la lunghezza dell'array indicato, in voci
22 21c new-instance vAA, type@BBBB A: registro di destinazione (8 bit)
B: indice di tipo
Costruisci una nuova istanza del tipo indicato, memorizzando un riferimento nella destinazione. Il tipo deve fare riferimento a una classe non array.
23 22c new-array vA, vB, type@CCCC A: registro di destinazione (4 bit)
B: registro della dimensione
C: indice del tipo
Costruisci un nuovo array del tipo e delle dimensioni indicati. Il tipo deve essere un tipo di array.
24 35c array-nuovo-completo {vC, vD, vE, vF, vG}, tipo@BBBB A: dimensione dell'array e numero di parole degli argomenti (4 bit)
B: indice di tipo (16 bit)
C..G: registri degli argomenti (4 bit ciascuno)
Costruisci un array del tipo e delle dimensioni specificati, riempiendolo con i contenuti forniti. Il tipo deve essere un tipo di array. I contenuti dell'array devono essere costituiti da una sola parola (ovvero non devono essere presenti array di long o double, ma sono accettabili i tipi di riferimento). L'istanza costruita viene memorizzata come "risultato" nello stesso modo in cui le istruzioni di chiamata del metodo memorizzano i risultati, pertanto l'istanza costruita deve essere spostata in un registro con un'istruzione move-result-object immediatamente successiva (se deve essere utilizzata).
25 3rc array/intervallo nuovo e completo {vCCCC .. vNNNN}, tipo@BBBB A: dimensione dell'array e numero di parole dell'argomento (8 bit)
B: indice di tipo (16 bit)
C: registro primo argomento (16 bit)
N = A + C - 1
Costruisci un array del tipo e delle dimensioni specificati, compilandolo con i contenuti forniti. I chiarimenti e le limitazioni sono gli stessi di filled-new-array, descritti sopra.
26 31t fill-array-data vAA, +BBBBBBBB (con i dati supplementari specificati di seguito in "Formato fill-array-data-payload") A: Riferimento all'array (8 bit)
B: Pseudo-istruzione di offset "branch" firmato ai dati della tabella (32 bit)
Compila l'array specificato con i dati indicati. Il riferimento deve essere a un array di elementi primitivi e la tabella di dati deve avere lo stesso tipo e non deve contenere più elementi di quelli che possono essere inseriti nell'array. In altre parole, l'array potrebbe essere più grande della tabella e, in questo caso, vengono impostati solo gli elementi iniziali dell'array, lasciando invariato il resto.
27 11x throw vAA A: registro con eccezioni (8 bit)
Genera l'eccezione indicata.
28 10t goto +AA A: offset del ramo con segno (8 bit) Passa incondizionatamente all'istruzione indicata.

Nota: l'offset del ramo non deve essere 0. Un loop girato può essere costruito legalmente con goto/32 o includendo un nop come target prima del ramo.

29 20t goto/16 +AAAA A: offset del ramo con segno (16 bit)
Passa incondizionatamente all'istruzione indicata.

Nota: l'offset del ramo non deve essere 0. Un loop girato può essere costruito legalmente con goto/32 o includendo un nop come target prima del ramo.

2a 30t goto/32 +AAAAAAAA A: offset del ramo con segno (32 bit)
Passa incondizionatamente all'istruzione indicata.
2b 31t packed-switch vAA, +BBBBBBBB (con dati supplementari come specificato di seguito in "Formato packed-switch-payload") A: register to test
B: offset "branch" firmato per pseudo-istruzione di dati di tabella (32 bit)
Passa a una nuova istruzione in base al valore nel registro specificato, utilizzando una tabella di offset corrispondenti a ciascun valore in un determinato intervallo di numeri interi, oppure passa all'istruzione successiva se non c'è corrispondenza.
2c 31t sparse-switch vAA, +BBBBBBBB (con dati supplementari come specificato di seguito in "Formato sparse-switch-payload") A: register to test
B: offset "branch" firmato per pseudo-istruzione di dati di tabella (32 bit)
Vai a una nuova istruzione in base al valore nel registro specificato, utilizzando una tabella ordinata di coppie di valori e offset oppure vai all'istruzione successiva se non c'è corrispondenza.
2d..31 23x cmpkind vAA, vBB, vCC
2d: cmpl-float (lt bias)
2e: cmpg-float (gt bias)
2f: cmpl-double (lt bias)
30: cmpg-double (gt bias)
31: cmp-long
A: registro di destinazione (8 bit)
B: prima coppia o primo registro di origine
C: seconda coppia o secondo registro di origine
Esegui il confronto indicato con numeri in virgola mobile o long, impostando a su 0 se b == c, su 1 se b > c o su -1 se b < c. Il "bias" elencato per le operazioni in virgola mobile indica come vengono trattati i confronti NaN: le istruzioni "gt bias" restituiscono 1 per i confronti NaN, mentre le istruzioni "lt bias" restituiscono -1.

Ad esempio, per verificare se il numero in virgola mobile è uguale a x < y, è consigliabile utilizzare cmpg-float. Un risultato pari a -1 indica che il test è stato vero e gli altri valori indicano che è stato falso a causa di un confronto valido o perché uno dei valori era NaN.

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: primo registro da testare (4 bit)
B: secondo registro da testare (4 bit)
C: offset del ramo con segno (16 bit)
Esegui il branch alla destinazione specificata se i valori dei due registri specificati corrispondono come specificato.

Nota: l'offset del ramo non deve essere 0. Un loop girato può essere costruito legalmente tramite un ramo intorno a un goto a ritroso o includendo un nop come target prima del ramo.

38..3d 21t if-testz vAA, +BBBB
38: if-eqz
39: if-nez
3a: if-ltz
3b: if-gez
3c: if-gtz
3d: if-lez
A: registro per il test (8 bit)
B: offset del ramo con segno (16 bit)
Esegui il branch alla destinazione specificata se il valore del registro specificato viene confrontato con 0 come specificato.

Nota: l'offset del ramo non deve essere 0. Un loop girato può essere costruito legalmente tramite un ramo intorno a un goto a ritroso o includendo un nop come destinazione prima del ramo.

3e..43 10x (non utilizzato)   (non utilizzato)
44..51 23x arrayop vAA, vBB, vCC
44: aget
45: aget-wide
46: aget-object
47: aget-boolean
48: aget-byte
49: aget-char
4a: aget-short
4b: aput
4c: aput-wide
4d: aput-object
4e: aput-boolean
4f: aput-byte
50: aput-char
51: aput-short
A: registro o coppia di valori; può essere di origine o di destinazione (8 bit)
B: registro array (8 bit)
C: registro di indice (8 bit)
Esegui l'operazione sull'array identificata nell'indice identificato della matrice specificata, caricando o memorizzando nel registro dei valori.
52,5 f 22 °C iinstanceop vA, vB, field@CCCC
52: iget
53: iget-wide
54: iget-object
55: iget-boolean
56: iget-byte
57: iget-char
58: iget-short
59: iput
5a: iput-wide
5b: iput-object
5c: iput-boolean
5d: iput-byte
5e: iput-char
5f: iput-short
A: registro o coppia di valori; può essere source o dest (4 bit)
B: registro oggetto (4 bit)
C: indice di riferimento del campo dell'istanza (16 bit)
Esegui l'operazione sul campo dell'istanza dell'oggetto identificato con il campo identificato, caricandolo o memorizzandolo nel registro dei valori.

Nota: questi opcode sono candidati ragionevoli per il collegamento statico, modificando l'argomento del campo in modo che sia un offset più diretto.

60..6d 21c sstaticop vAA, field@BBBB
60: sget
61: sget-wide
62: sget-object
63: sget-boolean
64: sget-byte
65: sget-char
66: sget-short
67: sput
68: sput-wide
69: sput-object
6a: sput-boolean
6b: sput-byte
6c: sput-char
6d: sput-short
A: registro o coppia di valori; può essere source o dest (8 bit)
B: indice di riferimento del campo statico (16 bit)
Esegui l'operazione sul campo statico dell'oggetto identificato con il campo statico identificato, caricandolo o memorizzandolo nel registro del valore.

Nota: questi opcode sono candidati ragionevoli per il collegamento statico, modificando l'argomento del campo in modo che sia un offset più diretto.

6e..72 35c invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB
6e: invoke-virtual
6f: invoke-super
70: invoke-direct
71: invoke-static
72: invoke-interface
A: numero di parole dell'argomento (4 bit)
B: indice di riferimento al metodo (16 bit)
C..G: registri degli argomenti (4 bit ciascuno)
Chiama il metodo indicato. Il risultato (se presente) può essere memorizzato con una variante move-result* appropriata come istruzione immediatamente successiva.

invoke-virtual viene utilizzato per invocare un normale metodo virtuale, ovvero un metodo diverso da static, private o un costruttore.

Quando method_id fa riferimento a un metodo di una classe non di interface, method_id viene utilizzato per invocare il metodo virtuale della superclasse più vicina (anziché quello con lo stesso method_id nella classe chiamante).invoke-super Si applicano le stesse limitazioni del metodo per invoke-virtual.

Nei file Dex della versione 037 o successive, se method_id fa riferimento a un metodo dell'interfaccia, invoke-super viene utilizzato per richiamare la versione più specifica e non sostituita del metodo definito in quell'interfaccia. valgono le stesse limitazioni per i metodi previste per invoke-virtual. Nei file Dex precedenti alla versione 037, l'interfaccia method_id è illegale e non definita.

invoke-direct viene utilizzato per invocare un metodo non direttostatic (ovvero un metodo di istanza che per sua natura non è sovrascrivibile, ovvero un metodo di istanza private o un costruttore).

invoke-static viene utilizzato per invocare un metodo static (che è sempre considerato un metodo diretto).

invoke-interface viene utilizzato per invocare un metodo interface, ovvero su un oggetto la cui classe concreta non è nota, utilizzando un method_id che fa riferimento a un interface.

Nota: questi opcode sono candidati ragionevoli per il collegamento statico, modificando l'argomento del metodo in modo che sia un offset più diretto (o una coppia di questi).

73 10x (non utilizzato)   (non utilizzato)
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: numero di parole dell'argomento (8 bit)
B: indice di riferimento al metodo (16 bit)
C: registro primo argomento (16 bit)
N = A + C - 1
Chiama il metodo indicato. Per dettagli, avvertimenti e suggerimenti, consulta la prima invoke-kind descrizione sopra.
79..7a 10x (non utilizzato)   (non utilizzato)
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: coppia o registro di destinazione (4 bit)
B: coppia o registro di origine (4 bit)
Esegui l'operazione unaria identificata sul registro di origine, memorizzando il risultato nel registro di destinazione.
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: coppia o registro di destinazione (8 bit)
B: coppia o registro di origine 1 (8 bit)
C: coppia o registro di origine 2 (8 bit)
Esegui l'operazione binaria identificata sui due registri di origine, memorizzando il risultato nel registro di destinazione.

Nota: a differenza di altre operazioni matematiche -long (che accettano coppie di registri sia per la prima che per la seconda origine), shl-long, shr-long e ushr-long accettano una coppia di registri per la prima origine (il valore da spostare), ma un singolo registro per la seconda origine (la distanza di spostamento).

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: coppia o registro di destinazione e prima origine (4 bit)
B: coppia o registro di seconda origine (4 bit)
Esegui l'operazione binaria identificata sui due registri di origine, memorizzando il risultato nel primo registro di origine.

Nota: a differenza di altre operazioni matematiche -long/2addr (che richiedono coppie di registri sia per la destinazione/la prima fonte sia per la seconda fonte), shl-long/2addr, shr-long/2addr e ushr-long/2addr richiedono una coppia di registri per la destinazione/la prima fonte (il valore da compensare), ma un singolo registro per la seconda fonte (la distanza di compensazione).

d0..d7 22s binop/lit16 vA, vB, #+CCCC
d0: add-int/lit16
d1: rsub-int (sottrazione inversa)
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: registro di destinazione (4 bit)
B: registro di origine (4 bit)
C: costante int firmata (16 bit)
Esegui l'operazione binaria indicata sul registro indicato (primo argomento) e sul valore letterale (secondo argomento), memorizzando il risultato nel registro di destinazione.

Nota: rsub-int non ha un suffisso poiché questa versione è l'opcode principale della relativa famiglia. Inoltre, di seguito sono riportati i dettagli sulla sua semantica.

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: registro di destinazione (8 bit)
B: registro di origine (8 bit)
C: costante int con segno (8 bit)
Esegui l'operazione binaria indicata sul registro indicato (primo argomento) e sul valore letterale (secondo argomento), memorizzando il risultato nel registro di destinazione.

Nota:di seguito sono riportati i dettagli sulla semantica di rsub-int.

e3..f9 10x (non utilizzato)   (non utilizzato)
fa 45cc invoke-polymorphic {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH A: numero di parole degli argomenti (4 bit)
B: indice di riferimento al metodo (16 bit)
C: ricevitore (4 bit)
D..G: registri degli argomenti (4 bit ciascuno)
H: indice di riferimento al prototipo (16 bit)
Richiama il metodo polimorfo della firma indicato. Il risultato (se presente) può essere memorizzato con una variante move-result* appropriata come istruzione immediatamente successiva.

Il riferimento al metodo deve essere a un metodo polimorfo con firma, ad esempio java.lang.invoke.MethodHandle.invoke o java.lang.invoke.MethodHandle.invokeExact.

Il destinatario deve essere un oggetto che supporta il metodo di firma polimorfa invocato.

Il riferimento al prototipo descrive i tipi di argomenti forniti e il tipo di ritorno previsto.

Il bytecode invoke-polymorphic potrebbe sollevare eccezioni durante l'esecuzione. Le eccezioni sono descritte nella documentazione dell'API per il metodo polimorfo della firma invocato.

Presente nei file Dex a partire dalla versione 038.
fb 4rcc invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH A: numero di parole degli argomenti (8 bit)
B: indice di riferimento al metodo (16 bit)
C: ricevitore (16 bit)
H: indice di riferimento al prototipo (16 bit)
N = A + C - 1
Richiama l'handle del metodo indicato. Per informazioni dettagliate, consulta la descrizione di invoke-polymorphic.

Presente nei file Dex a partire dalla versione 038.
fc 35c invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB A: numero di parole degli argomenti (4 bit)
B: indice di riferimento del sito di chiamata (16 bit)
C..G: registri degli argomenti (4 bit ciascuno)
Risolve e richiama il sito di chiamata indicato. Il risultato dell'invocazione (se presente) può essere archiviato con una variante move-result* appropriata come istruzione immediatamente successiva.

Questa istruzione viene eseguita in due fasi: risoluzione del sito di chiamata e chiamata del sito di chiamata.

La risoluzione del sito di chiamata verifica se il sito di chiamata indicato ha un'istanza java.lang.invoke.CallSite associata. In caso contrario, il metodo del linker di bootstrap per il sito di chiamata indicato viene invocato utilizzando gli argomenti presenti nel file DEX (vedi call_site_item). Il metodo del linker di bootstrap restituisce un'istanza java.lang.invoke.CallSite che verrà poi associata al sito di chiamata indicato se non esiste alcuna associazione. È possibile che un altro thread abbia già eseguito l'associazione per primo. In questo caso, l'esecuzione dell'istruzione continua con la prima istanza java.lang.invoke.CallSite associata.

Viene eseguita l'invocazione del sito di chiamata sul java.lang.invoke.MethodHandle target dell'istanza java.lang.invoke.CallSite risolta. Il target viene invocato come se si eseguisse invoke-polymorphic (descritto sopra) utilizzando l'handle metodo e gli argomenti dell'istruzione invoke-custom come argomenti di un'invocazione dell'handle metodo esatto.

Le eccezioni sollevate dal metodo del linker di bootstrap sono racchiuse in un java.lang.BootstrapMethodError. Un BootstrapMethodError viene visualizzato anche se:
  • Il metodo del linker di bootstrap non restituisce un'istanza java.lang.invoke.CallSite.
  • Il java.lang.invoke.CallSite restituito ha un null metodo di gestione del target.
  • Il target dell'handle del metodo non è del tipo richiesto.
Presente nei file Dex a partire dalla versione 038.
fd 3rc invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB A: numero di parole dell'argomento (8 bit)
B: indice di riferimento del sito di chiamata (16 bit)
C: registro primo argomento (16 bit)
N = A + C - 1
Risolvi e richiama un sito di chiamata. Per informazioni dettagliate, consulta la descrizione di invoke-custom.

Presente nei file Dex a partire dalla versione 038.
fe 21c const-method-handle vAA, method_handle@BBBB A: registro di destinazione (8 bit)
B: indice dell'handle metodo (16 bit)
Sposta un riferimento all'handle del metodo specificato dall'indice dato nel registro specificato.

Presente nei file Dex a partire dalla versione 039.
ff 21c const-method-type vAA, proto@BBBB A: registro di destinazione (8 bit)
B: riferimento al prototipo del metodo (16 bit)
Sposta un riferimento al prototipo del metodo specificato dall'indice dato nel registro specificato.

Presente nei file Dex a partire dalla versione 039.

Formato del payload del pacchetto di switch

Nome Formato Descrizione
ident ushort = 0x0100 Identificazione di pseudo-opcode
dimensioni ushort numero di voci nella tabella
first_key int primo (e più basso) valore della condizione di switch
target int[] Elenco di size target di ramo relativi. I target sono relativi all'indirizzo dell'opcode di switch, non di questa tabella.

Nota: il numero totale di unità di codice per un'istanza di questa tabella è (size * 2) + 4.

Formato sparse-switch-payload

Nome Formato Descrizione
ident ushort = 0x0200 Identificazione di pseudo-opcode
dimensioni ushort numero di voci nella tabella
chiavi int[] elenco di valori chiave size, ordinati dal più basso al più alto
target int[] elenco di size target di ramo relativi, ciascuno corrispondente al valore della chiave nello stesso indice. I target sono relativi all'indirizzo dell'opcode di switch, non di questa tabella.

Nota: il numero totale di unità di codice per un'istanza di questa tabella è (size * 4) + 2.

formato del payload dei dati dell'array di completamento

Nome Formato Descrizione
ident ushort = 0x0300 Identificazione di pseudo-opcode
element_width ushort numero di byte in ogni elemento
dimensioni uint numero di elementi nella tabella
di dati ubyte[] valori dei dati

Nota: il numero totale di unità di codice per un'istanza di questa tabella è (size * element_width + 1) / 2 + 4.

Dettagli dell'operazione matematica

Nota: le operazioni in virgola mobile devono rispettare le regole IEEE 754, utilizzando il metodo di arrotondamento al numero più vicino e il sottoflusso graduale, salvo diversa indicazione.

Opcode Semantica del linguaggio C Note
neg-int int32 a;
int32 result = -a;
Complemento a due unario.
not-int int32 a;
int32 result = ~a;
Unario a complemento a 1.
neg-long int64 a;
int64 result = -a;
Complemento a due unario.
not-long int64 a;
int64 result = ~a;
Unario a complemento a 1.
neg-float float a;
float result = -a;
Negazione a virgola mobile.
neg-double double a;
double result = -a;
Negazione a virgola mobile.
int-to-long int32 a;
int64 result = (int64) a;
Firma l'estensione di int32 in int64.
int-to-float int32 a;
float result = (float) a;
Conversione di int32 in float con arrotondamento al numero intero più vicino. In questo modo si perde precisione per alcuni valori.
int-to-double int32 a;
double result = (double) a;
Conversione di int32 in double.
long-to-int int64 a;
int32 result = (int32) a;
Troncamento di int64 in int32.
long-to-float int64 a;
float result = (float) a;
Conversione di int64 in float con arrotondamento al numero intero più vicino. In questo modo si perde precisione per alcuni valori.
long-to-double int64 a;
double result = (double) a;
Conversione di int64 in double con arrotondamento al numero intero più vicino. In questo modo si perde precisione per alcuni valori.
float-to-int float a;
int32 result = (int32) a;
Conversione di float in int32 con arrotondamento per difetto. NaN e -0.0 (zero negativo) vengono convertiti nell'intero 0. Gli infiniti e i valori con un valore assoluto troppo elevato per essere rappresentato vengono convertiti in 0x7fffffff o -0x80000000 a seconda del segno.
float-to-long float a;
int64 result = (int64) a;
Conversione di float in int64 con arrotondamento per difetto. Qui si applicano le stesse regole per i casi speciali valide per float-to-int, tranne per il fatto che i valori fuori intervallo vengono convertiti in 0x7fffffffffffffff o -0x8000000000000000 a seconda del segno.
float-to-double float a;
double result = (double) a;
Conversione di float in double, mantenendo esattamente il valore.
double-to-int double a;
int32 result = (int32) a;
Conversione di double in int32 con arrotondamento per difetto. Valgono le stesse regole per i casi speciali valide per float-to-int.
double-to-long double a;
int64 result = (int64) a;
Conversione di double in int64 con arrotondamento per difetto. Valgono le stesse regole per i casi speciali valide per float-to-long.
double-to-float double a;
float result = (float) a;
Conversione di double in float con arrotondamento al numero intero più vicino. In questo modo si perde precisione per alcuni valori.
int-to-byte int32 a;
int32 result = (a << 24) >> 24;
Troncamento di int32 a int8, segno che estende il risultato.
int-to-char int32 a;
int32 result = a & 0xffff;
Troncamento di int32 a uint16, senza estensione del segno.
int-to-short int32 a;
int32 result = (a << 16) >> 16;
Troncamento di int32 a int16, segno che estende il risultato.
add-int int32 a, b;
int32 result = a + b;
Somma con il complemento a due.
sub-int int32 a, b;
int32 result = a - b;
Sottrazione con il complemento a due.
rsub-int int32 a, b;
int32 result = b - a;
Sottrazione inversa con il complemento a due.
mul-int int32 a, b;
int32 result = a * b;
Moltiplicazione con il complemento a due.
div-int int32 a, b;
int32 result = a / b;
Divisione con il complemento a due, arrotondata per difetto (ovvero troncata a numero intero). Viene generato un errore ArithmeticException se b == 0.
rem-int int32 a, b;
int32 result = a % b;
Resto del complemento a due dopo la divisione. Il segno del risultato è uguale a quello di a ed è definito con maggiore precisione come result == a - (a / b) * b. Viene generato un ArithmeticException se b == 0.
and-int int32 a, b;
int32 result = a & b;
E a livello di bit.
or-int int32 a, b;
int32 result = a | b;
O a livello di bit.
xor-int int32 a, b;
int32 result = a ^ b;
XOR a livello di bit.
shl-int int32 a, b;
int32 result = a << (b & 0x1f);
Spostamento a sinistra a livello di bit (con argomento mascherato).
shr-int int32 a, b;
int32 result = a >> (b & 0x1f);
Spostamento a destra con segno a livello di bit (con argomento mascherato).
ushr-int uint32 a, b;
int32 result = a >> (b & 0x1f);
Spostamento a destra senza segno a livello di bit (con argomento mascherato).
add-long int64 a, b;
int64 result = a + b;
Somma con il complemento a due.
sottolunghezza int64 a, b;
int64 result = a - b;
Sottrazione con il complemento a due.
mul-long int64 a, b;
int64 result = a * b;
Moltiplicazione con il complemento a due.
div-long int64 a, b;
int64 result = a / b;
Divisione con il complemento a due, arrotondata per difetto (ovvero troncata a numero intero). Viene generato un errore ArithmeticException se b == 0.
rem-long int64 a, b;
int64 result = a % b;
Resto del complemento a due dopo la divisione. Il segno del risultato è uguale a quello di a ed è definito con maggiore precisione come result == a - (a / b) * b. Viene generato un ArithmeticException se b == 0.
and-long int64 a, b;
int64 result = a & b;
E a livello di bit.
or-long int64 a, b;
int64 result = a | b;
O a livello di bit.
xor-long int64 a, b;
int64 result = a ^ b;
XOR a livello di bit.
shl-long int64 a;
int32 b;
int64 result = a << (b & 0x3f);
Spostamento a sinistra a livello di bit (con argomento mascherato).
shr-long int64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Spostamento a destra con segno a livello di bit (con argomento mascherato).
ushr-long uint64 a;
int32 b;
int64 result = a >> (b & 0x3f);
Spostamento a destra senza segno a livello di bit (con argomento mascherato).
add-float float a, b;
float result = a + b;
Somma con virgola mobile.
sotto-float float a, b;
float result = a - b;
Sottrazione con virgola mobile.
mul-float float a, b;
float result = a * b;
Moltiplicazione in virgola mobile.
div-float float a, b;
float result = a / b;
Divisione con virgola mobile.
rem-float float a, b;
float result = a % b;
Resto in virgola mobile dopo la divisione. Questa funzione è diversa dal resto IEEE 754 ed è definita come result == a - roundTowardZero(a / b) * b.
add-double double a, b;
double result = a + b;
Somma con virgola mobile.
doppia mini double a, b;
double result = a - b;
Sottrazione con virgola mobile.
mul-double double a, b;
double result = a * b;
Moltiplicazione in virgola mobile.
div-double double a, b;
double result = a / b;
Divisione con virgola mobile.
rem-double double a, b;
double result = a % b;
Resto in virgola mobile dopo la divisione. Questa funzione è diversa dal resto IEEE 754 ed è definita come result == a - roundTowardZero(a / b) * b.