Bytecode di Dalvik

Disegno generale

  • Il modello di macchina e le convenzioni di chiamata hanno lo scopo di imitare approssimativamente le comuni architetture reali e le convenzioni di chiamata in stile C:
    • La macchina è basata sui registri e le dimensioni dei frame vengono fissate al momento della creazione. Ogni frame è costituito da un numero particolare di registri (specificato dal metodo) nonché da eventuali dati aggiuntivi necessari per eseguire il metodo, come (ma non limitato a) il contatore del programma e un riferimento al file .dex che contiene il metodo .
    • Quando vengono utilizzati per valori di bit (come numeri interi e numeri in virgola mobile), i registri sono considerati larghi 32 bit. Le coppie di registri adiacenti vengono utilizzate per valori a 64 bit. Non è richiesto l'allineamento per le coppie di registri.
    • Quando vengono utilizzati per i riferimenti a oggetti, i registri sono considerati sufficientemente ampi da contenere esattamente uno di questi riferimenti.
    • In termini di rappresentazione bit per bit, (Object) null == (int) 0 .
    • Gli N argomenti di un metodo atterrano negli ultimi N registri del frame di chiamata del metodo, in ordine. Gli argomenti ampi consumano due registri. Ai metodi di istanza viene passato un riferimento this come primo argomento.
  • L'unità di archiviazione nel flusso di istruzioni è una quantità senza segno a 16 bit. Alcuni bit in alcune istruzioni vengono ignorati/devono essere zero.
  • Le istruzioni non sono limitate gratuitamente a un tipo particolare. Ad esempio, le istruzioni che spostano valori di registro a 32 bit senza interpretazione non devono specificare se stanno spostando valori interi o float.
  • Esistono pool di costanti enumerati e indicizzati separatamente per i riferimenti a stringhe, tipi, campi e metodi.
  • I dati letterali bit per bit sono rappresentati in linea nel flusso di istruzioni.
  • Poiché, in pratica, è raro che un metodo richieda più di 16 registri e poiché la necessità di più di otto registri è ragionevolmente comune, molte istruzioni si limitano a indirizzare solo i primi 16 registri. Quando ragionevolmente possibile, le istruzioni consentono riferimenti fino ai primi 256 registri. Inoltre, alcune istruzioni hanno varianti che consentono conteggi di registri molto più grandi, tra cui un paio di istruzioni di move catch-all che possono indirizzare i registri nell'intervallo v0v65535 . Nei casi in cui una variante di istruzione non è disponibile per indirizzare un registro desiderato, ci si aspetta che il contenuto del registro venga spostato dal registro originale a un registro basso (prima dell'operazione) e/o spostato da un registro di risultato basso a uno alto registrarsi (dopo l'operazione).
  • Esistono diverse "pseudo-istruzioni" utilizzate per contenere payload di dati a lunghezza variabile, a cui si fa riferimento con istruzioni regolari (ad esempio, fill-array-data ). Tali istruzioni non devono mai essere incontrate durante il normale flusso di esecuzione. Inoltre, le istruzioni devono trovarsi su offset bytecode con numero pari (ovvero allineati a 4 byte). Per soddisfare questo requisito, gli strumenti di generazione dex devono emettere un'istruzione nop aggiuntiva come spaziatore se tale istruzione non sarebbe altrimenti allineata. Infine, sebbene non richiesto, si prevede che la maggior parte degli strumenti sceglierà di emettere queste istruzioni alla fine dei metodi, poiché altrimenti sarebbe probabile che sarebbero necessarie istruzioni aggiuntive per diramarsi attorno ad esse.
  • Quando sono installate su un sistema in esecuzione, alcune istruzioni possono essere modificate, cambiando il loro formato, come ottimizzazione del collegamento statico durante l'installazione. Questo per consentire un'esecuzione più rapida una volta che il collegamento è noto. Vedere il documento relativo ai formati di istruzione per le varianti suggerite. La parola "suggerito" è usata di proposito; non è obbligatorio implementarli.
  • Sintassi umana e mnemonica:
    • Ordinamento Dest-then-source per gli argomenti.
    • Alcuni codici operativi hanno un suffisso del nome disambiguato per indicare il tipo o i tipi su cui operano:
      • I codici operativi a 32 bit di tipo generale non sono contrassegnati.
      • I codici operativi a 64 bit di tipo generale hanno il suffisso -wide .
      • Gli opcode specifici del tipo hanno il suffisso del loro tipo (o una semplice abbreviazione), uno tra: -boolean -byte -char -short -int -long -float -double -object -string -class -void .
    • Alcuni codici operativi hanno un suffisso disambiguato per distinguere operazioni altrimenti identiche che hanno layout o opzioni di istruzioni diversi. Questi suffissi sono separati dai nomi principali con una barra (" / ") ed esistono principalmente per fare in modo che ci sia una mappatura uno-a-uno con costanti statiche nel codice che genera e interpreta gli eseguibili (cioè per ridurre l'ambiguità per l'uomo).
    • Nelle descrizioni qui presenti, l'ampiezza di un valore (che indica, ad esempio, l'intervallo di una costante o il numero di registri eventualmente indirizzati) è enfatizzata dall'uso di un carattere per quattro bit di larghezza.
    • Ad esempio, nell'istruzione " move-wide/from16 vAA, vBBBB ":
      • " move " è il codice operativo 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 wide (64 bit).
      • " from16 " è il suffisso del codice operativo, che indica una variante che ha un riferimento di registro a 16 bit come origine.
      • " vAA " è il registro di destinazione (implicito nell'operazione; ancora una volta, la regola è che gli argomenti di destinazione vengono sempre per primi), che deve essere compreso nell'intervallo v0v255 .
      • " vBBBB " è il registro di origine, che deve essere compreso nell'intervallo v0v65535 .
  • Consulta il documento sui formati di istruzione per maggiori dettagli sui vari formati di istruzione (elencati in "Op & Format") e dettagli sulla sintassi del codice operativo.
  • Vedere il documento in formato file .dex per maggiori dettagli su dove si inserisce il bytecode nell'immagine più grande.

Riepilogo del set di bytecode

Op e formato Mnemonico/Sintassi argomenti Descrizione
00 10x no Cicli dei rifiuti.

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

01 12x sposta vA, vB A: registro di destinazione (4 bit)
B: registro sorgente (4 bit)
Sposta il contenuto di un registro non oggetto in un altro.
02 22x sposta/da 16 vAA, vBBBB A: registro di destinazione (8 bit)
B: registro sorgente (16 bit)
Sposta il contenuto di un registro non oggetto in un altro.
03 32x mossa/16 vAAAA, vBBBB A: registro di destinazione (16 bit)
B: registro sorgente (16 bit)
Sposta il contenuto di un registro non oggetto in un altro.
04 12x a tutto il movimento vA, vB A: coppia di registri di destinazione (4 bit)
B: coppia di registri sorgente (4 bit)
Sposta il contenuto di una coppia di registri in un'altra.

Nota: è legale passare da v N a v N-1 o v N+1 , quindi le implementazioni devono fare in modo che entrambe le metà di una coppia di registri vengano lette prima che qualsiasi cosa venga scritta.

05 22x a tutto campo/da 16 vAA, vBBBB A: coppia di registri di destinazione (8 bit)
B: coppia di registri sorgente (16 bit)
Sposta il contenuto 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 sorgente (16 bit)
Sposta il contenuto di una coppia di registri in un'altra.

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

07 12x sposta-oggetto vA, vB A: registro di destinazione (4 bit)
B: registro sorgente (4 bit)
Sposta il contenuto di un registro porta oggetti in un altro.
08 22x sposta-oggetto/da 16 vAA, vBBBB A: registro di destinazione (8 bit)
B: registro sorgente (16 bit)
Sposta il contenuto di un registro porta oggetti in un altro.
09 32x sposta-oggetto/16 vAAAA, vBBBB A: registro di destinazione (16 bit)
B: registro sorgente (16 bit)
Sposta il contenuto di un registro porta oggetti in un altro.
0a 11x move-risultato vAA A: registro di destinazione (8 bit) Spostare il risultato non-oggetto a parola singola del invoke- kind di chiamata più recente nel registro indicato. Questo deve essere fatto come istruzione immediatamente dopo un invoke- kind cui risultato (a parola singola, non oggetto) non deve essere ignorato; altrove non è valido.
0b 11x Move-result-wide vAA A: coppia di registri di destinazione (8 bit) Sposta il risultato della doppia parola del invoke- kind di chiamata più recente nella coppia di registri indicata. Questo deve essere fatto come istruzione immediatamente dopo un invoke- kind cui risultato (doppia parola) non deve essere ignorato; altrove non è valido.
0c 11x spostare-risultato-oggetto vAA A: registro di destinazione (8 bit) Sposta il risultato dell'oggetto del invoke- kind di chiamata più recente nel registro indicato. Questo deve essere fatto come istruzione immediatamente dopo invoke- kind o filled-new-array il cui risultato (oggetto) non deve essere ignorato; altrove non è valido.
0d 11x mossa-eccezione vAA A: registro di destinazione (8 bit) Salva un'eccezione appena rilevata nel registro specificato. Questa deve essere la prima istruzione di qualsiasi gestore di eccezioni la cui eccezione rilevata non deve essere ignorata e questa istruzione deve verificarsi solo come prima istruzione di un gestore di eccezioni; altrove non è valido.
0e 10x ritorno-vuoto Ritorno da un metodo void .
0f 11x restituire vAA A: registro del valore di ritorno (8 bit) Restituzione da un metodo di restituzione del valore non oggetto a larghezza singola (32 bit).
10 11x vAA a livello di ritorno A: valore di ritorno coppia di registri (8 bit) Restituzione da un metodo di restituzione del valore a doppia larghezza (64 bit).
11 11x oggetto di ritorno vAA A: registro del valore di ritorno (8 bit) Ritorno da un metodo di restituzione di oggetti.
12 11n cost/4 vA, #+B A: registro di destinazione (4 bit)
B: firmato int (4 bit)
Sposta il valore letterale specificato (esteso di segno a 32 bit) nel registro specificato.
13 21s const/16 vAA, #+BBBB A: registro di destinazione (8 bit)
B: firmato int (16 bit)
Sposta il valore letterale specificato (esteso di segno 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: firmato int (16 bit)
Sposta il valore letterale specificato (zero destro esteso a 32 bit) nel registro specificato.
16 21s const-wide/16 vAA, #+BBBB A: registro di destinazione (8 bit)
B: firmato int (16 bit)
Sposta il valore letterale dato (segno esteso a 64 bit) nella coppia di registri specificata.
17 31i const-wide/32 vAA, #+BBBBBBBB A: registro di destinazione (8 bit)
B: firmato int (32 bit)
Sposta il valore letterale dato (segno esteso a 64 bit) nella coppia di registri specificata.
18 51l const-wide vAA, #+BBBBBBBBBBBBBBBBBB 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: firmato int (16 bit)
Sposta il valore letterale dato (zero destro esteso a 64 bit) nella coppia di registri specificata.
1a 21c const-string vAA, stringa@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, tipo@BBBB A: registro di destinazione (8 bit)
B: tipo indice
Sposta un riferimento alla classe specificata dall'indice specificato nel registro specificato. Nel caso in cui il tipo indicato sia primitivo, questo memorizzerà un riferimento alla classe degenerata del tipo primitivo.
1d 11x monitor-enter vAA A: registro di riferimento (8 bit) Acquisisci il monitor per l'oggetto indicato.
1e 11x monitor-uscita vAA A: registro di riferimento (8 bit) Rilasciare il monitor per l'oggetto indicato.

Nota: se questa istruzione deve generare un'eccezione, deve farlo come se il PC fosse già avanzato oltre l'istruzione. Può essere utile pensare a questo come all'istruzione eseguita con successo (in un certo senso) e all'eccezione che viene generata dopo l'istruzione ma prima che quella successiva abbia la possibilità di essere eseguita. Questa definizione consente a un metodo di utilizzare un blocco catch-all (ad esempio, finally ) di pulizia del monitor come pulizia del monitor per quel blocco stesso, come un modo per gestire le eccezioni arbitrarie che potrebbero essere generate a causa dell'implementazione storica di Thread.stop() , pur riuscendo a mantenere una corretta igiene del monitor.

1f 21c check-cast vAA, digita @BBBB A: registro di riferimento (8 bit)
B: tipo indice (16 bit)
Genera un ClassCastException se non è possibile eseguire il cast del riferimento nel registro specificato al tipo indicato.

Nota: poiché A deve sempre essere un riferimento (e non un valore primitivo), questo fallirà necessariamente in fase di esecuzione (ovvero genererà un'eccezione) se B fa riferimento a un tipo primitivo.

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

Nota: poiché B deve sempre essere un riferimento (e non un valore primitivo), ciò comporterà sempre la memorizzazione di 0 se C si riferisce a un tipo primitivo.

21 12x lunghezza dell'array vA, vB A: registro di destinazione (4 bit)
B: registro di riferimento dell'array (4 bit)
Memorizzare nel registro di destinazione indicato la lunghezza dell'array indicato, in voci
22 21c nuova istanza vAA, tipo@BBBB A: registro di destinazione (8 bit)
B: tipo indice
Costruire una nuova istanza del tipo indicato, memorizzando un riferimento ad essa 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 delle taglie
C: tipo indice
Costruisci un nuovo array del tipo e delle dimensioni indicate. Il tipo deve essere un tipo di matrice.
24 35c riempito-nuovo-array {vC, vD, vE, vF, vG}, tipo@BBBB A: dimensione dell'array e conteggio delle parole dell'argomento (4 bit)
B: tipo indice (16 bit)
C..G: registri argomenti (4 bit ciascuno)
Costruisci un array del tipo e della dimensione indicati, riempiendolo con il contenuto fornito. Il tipo deve essere un tipo di matrice. Il contenuto dell'array deve essere a parola singola (ovvero, nessun array di long o double , ma i tipi di riferimento sono accettabili). L'istanza costruita viene archiviata come "risultato" nello stesso modo in cui le istruzioni di chiamata al metodo memorizzano i loro risultati, quindi l'istanza costruita deve essere spostata in un registro con un'istruzione move-result-object immediatamente successiva (se deve essere utilizzata ).
25 3rc riempito-nuovo-array/intervallo {vCCCC .. vNNNN}, digita @BBBB A: dimensione dell'array e conteggio delle parole dell'argomento (8 bit)
B: tipo indice (16 bit)
C: registro del primo argomento (16 bit)
N = A + C - 1
Costruisci un array del tipo e della dimensione indicati, riempiendolo con il contenuto fornito. I chiarimenti e le restrizioni sono gli stessi di filled-new-array , descritto sopra.
26 31t fill-array-data vAA, +BBBBBBBB (con dati supplementari come specificato di seguito in " fill-array-data-payload Format") A: riferimento all'array (8 bit)
B: "ramo" con segno offset per la pseudo-istruzione dei dati della tabella (32 bit)
Riempi la matrice data con i dati indicati. Il riferimento deve essere a un array di primitive e la tabella di dati deve corrispondere al tipo e non deve contenere più elementi di quelli che rientreranno nell'array. Cioè, l'array può essere più grande della tabella e, in tal caso, vengono impostati solo gli elementi iniziali dell'array, lasciando solo il resto.
27 11x lancia vAA A: registro con eccezioni (8 bit)
Lancia l'eccezione indicata.
28 10 t vai a +AA A: offset ramo con segno (8 bit) Salta incondizionatamente all'istruzione indicata.

Nota: l'offset del ramo non deve essere 0 . (Uno spin loop può essere legalmente costruito con goto/32 o includendo un nop come obiettivo prima del ramo.)

29 20 t vai a/16 +AAAA A: offset ramo con segno (16 bit)
Salta incondizionatamente all'istruzione indicata.

Nota: l'offset del ramo non deve essere 0 . (Uno spin loop può essere legalmente costruito con goto/32 o includendo un nop come obiettivo prima del ramo.)

2a 30t vai a/32 +AAAAAAAA A: offset ramo con segno (32 bit)
Salta incondizionatamente all'istruzione indicata.
2b 31t pack-switch vAA, +BBBBBBBB (con dati supplementari come specificato di seguito in "package packed-switch-payload Format") A: registrati per testare
B: "ramo" con segno offset per la pseudo-istruzione dei dati della tabella (32 bit)
Passa a una nuova istruzione in base al valore nel registro specificato, utilizzando una tabella di offset corrispondente a ciascun valore in un particolare intervallo integrale, 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: registrati per testare
B: "ramo" con segno offset per la pseudo-istruzione dei dati della tabella (32 bit)
Passa a una nuova istruzione in base al valore nel registro specificato, utilizzando una tabella ordinata di coppie valore-offset, oppure passa all'istruzione successiva se non c'è corrispondenza.
2d..31 23x tipo cmp vAA, vBB, vCC
2d: cmpl-float (lt bias)
2e: cmpg-float (gt bias)
2f: cmpl-doppio (lt bias)
30: cmpg-doppio (gt bias)
31: cmp-lungo
A: registro di destinazione (8 bit)
B: primo registro sorgente o coppia
C: secondo registro sorgente o coppia
Eseguire il confronto a virgola mobile o long indicato, impostando a su 0 se b == c , 1 se b > c o -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 e le istruzioni "lt bias" restituiscono -1 .

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

32..37 22t if- test vA, vB, +CCCC
32: se-eq
33: se-ne
34: se-lt
35: se-ge
36: se-gt
37: se-le
A: primo registro da testare (4 bit)
B: secondo registro da testare (4 bit)
C: offset ramo con segno (16 bit)
Diramare alla destinazione data se i valori dei due registri dati si confrontano come specificato.

Nota: l'offset del ramo non deve essere 0 . (Uno spin loop può essere legalmente costruito ramificandosi attorno a un goto all'indietro o includendo un nop come bersaglio prima del ramo.)

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

Nota: l'offset del ramo non deve essere 0 . (Uno spin loop può essere legalmente costruito ramificandosi attorno a un goto all'indietro o includendo un nop come bersaglio prima del ramo.)

3e..43 10x (non utilizzato) (non utilizzato)
44..51 23x arrayop vAA, vBB, vCC
44: ottenere
45: a tutto campo
46: aget-oggetto
47: aget-booleano
48: aget-byte
49: get-char
4a: aget-breve
4b: aput
4c: aput-wide
4d: aput-oggetto
4e: aput-booleano
4f: aput-byte
50: aput-char
51: aput-breve
A: registro o coppia di valori; può essere sorgente o destinazione (8 bit)
B: registro array (8 bit)
C: registro indice (8 bit)
Eseguire l'operazione sull'array identificato all'indice identificato dell'array specificato, caricandolo o memorizzandolo nel registro dei valori.
52..5f 22c i instanceop vA, vB, field@CCCC
52: ottengo
53: iget-wide
54: iget-oggetto
55: iget-booleano
56: iget-byte
57: iget-char
58: iget-breve
59: immesso
5a: a livello di iput
5b: iput-oggetto
5c: iput-booleano
5d: iput-byte
5e: iput-char
5f: iput-breve
A: registro o coppia di valori; può essere sorgente o destinazione (4 bit)
B: registro oggetto (4 bit)
C: indice di riferimento del campo di istanza (16 bit)
Eseguire l'operazione sul campo dell'istanza dell'oggetto identificato con il campo identificato, caricandolo o memorizzandolo nel registro dei valori.

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

60..6d 21c sstaticop vAA, campo@BBBB
60: seg
61: largo
62: sget-oggetto
63: sget-booleano
64: sget-byte
65: sget-char
66: breve
67: sputare
68: a tutto tondo
69: oggetto-sput
6a: sput-booleano
6b: byte di sput
6c: sput-char
6d: cortocircuito
A: registro o coppia di valori; può essere sorgente o destinazione (8 bit)
B: indice di riferimento campo statico (16 bit)
Eseguire l'operazione sul campo statico dell'oggetto identificato con il campo statico identificato, caricandolo o memorizzandolo nel registro dei valori.

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

6e..72 35c invoke- tipo {vC, vD, vE, vF, vG}, meth@BBBB
6e: invoca-virtuale
6f: invoca-super
70: invocare diretto
71: invoca-statico
72: interfaccia di chiamata
A: conteggio parole argomento (4 bit)
B: indice di riferimento del metodo (16 bit)
C..G: registri argomenti (4 bit ciascuno)
Chiama il metodo indicato. Il risultato (se presente) può essere memorizzato con un'appropriata variante move-result* come istruzione immediatamente successiva.

invoke-virtual viene utilizzato per invocare un normale metodo virtuale (un metodo che non è private , static o final e non è nemmeno un costruttore).

Quando method_id fa riferimento a un metodo di una classe non di interfaccia, invoke-super viene utilizzato per invocare il metodo virtuale della superclasse più vicina (al contrario di quello con lo stesso method_id nella classe chiamante). Le stesse restrizioni sui metodi valgono come per invoke-virtual .

Nei file Dex versione 037 o successiva, se method_id fa riferimento a un metodo di interfaccia, viene utilizzato invoke-super per richiamare la versione più specifica e non sovrascritta di quel metodo definito su quell'interfaccia. Le stesse restrizioni sui metodi valgono come per invoke-virtual . Nei file Dex precedenti alla versione 037 , avere un'interfaccia method_id è illegale e non definito.

invoke-direct viene utilizzato per invocare un metodo diretto non static (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 di interface , ovvero su un oggetto la cui classe concreta non è nota, utilizzando un method_id che fa riferimento a interface .

Nota: questi codici operativi sono candidati ragionevoli per il collegamento statico, alterando 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- tipo /range {vCCCC .. vNNNN}, meth@BBBB
74: invoca-virtuale/intervallo
75: invoca-super/intervallo
76: richiamo diretto/intervallo
77: invoca-statico/intervallo
78: interfaccia/intervallo di chiamata
A: conteggio parole argomento (8 bit)
B: indice di riferimento del metodo (16 bit)
C: registro del primo argomento (16 bit)
N = A + C - 1
Chiama il metodo indicato. Vedere la descrizione invoke- kind sopra per dettagli, avvertimenti e suggerimenti.
79..7a 10x (non utilizzato) (non utilizzato)
7b..8f 12x unop vA, vB
7b: neg-int
7c: non-int
7d: neg-lungo
7e: non lungo
7f: galleggiante negativo
80: neg-doppio
81: da int a lungo
82: int-float
83: da int a doppio
84: da lungo a int
85: lunga per galleggiare
86: da lungo a doppio
87: float-int
88: da galleggiante a lungo
89: float-to-double
8a: da doppio a int
8b: da doppio a lungo
8c: double-float
8d: da int a byte
8e: da int a char
8f: da int a corto
A: registro o coppia di destinazione (4 bit)
B: registro sorgente o coppia (4 bit)
Eseguire l'operazione unaria identificata sul registro di origine, memorizzando il risultato nel registro di destinazione.
90..af 23x binop vAA, vBB, vCC
90: additivo
91: sub-int
92: mul-int
93: div-int
94: rem-int
95: e-int
96: o-int
97: xor-int
98: shl-int
99: sh-int
9a: ushr-int
9b: add-long
9c: sub-lungo
9d: mul-lungo
9e: div-lungo
9f: rem-lungo
a0: e-lungo
a1: o-lungo
a2: xor-lungo
a3: shl-lungo
a4: sh-lungo
a5: ushr-lungo
a6: aggiungere-flottante
a7: sub-flottante
a8: mul-float
a9: div-float
aa: rem-flottante
ab: somma-doppio
ac: sub-doppio
annuncio: mul-doppio
ae: div-doppio
af: rem-doppio
A: registro o coppia di destinazione (8 bit)
B: primo registro sorgente o coppia (8 bit)
C: secondo registro sorgente o coppia (8 bit)
Eseguire l'operazione binaria identificata sui due registri di origine, memorizzando il risultato nel registro di destinazione.

Nota: contrariamente ad altre operazioni matematiche -long (che accettano coppie di registri sia per la prima che per la seconda sorgente), shl-long , shr-long e ushr-long prendono una coppia di registri per la prima sorgente (il valore da spostare ), ma un unico registro per la loro seconda sorgente (la distanza di spostamento).

b0..cf 12x binop /2addr vA, vB
b0: add-int/2addr
b1: sub-int/2addr
b2: mul-int/2ind
b3: div-int/2addr
b4: rem-int/2addr
b5: e-int/2addr
b6: or-int/2addr
b7: xor-int/2addr
b8: shl-int/2addr
b9: sh-int/2addr
ba: ushr-int/2addr
bb: add-long/2addr
bc: sub-lungo/2addr
bd: mul-long/2addr
essere: div-lungo/2addr
bf: rem-lungo/2addr
c0: e-lungo/2addr
c1: o-lungo/2addr
c2: xor-lungo/2addr
c3: shl-lungo/2addr
c4: sh-lungo/2addr
c5: ushr-lungo/2addr
c6: add-float/2addr
c7: sub-float/2addr
c8: mul-float/2addr
c9: div-float/2addr
ca: rem-float/2addr
cb: add-doppio/2addr
cc: sub-doppio/2ind
cd: mul-doppio/2addr
ce: div-doppio/2addr
cfr: rem-doppio/2addr
A: destinazione e primo registro o coppia di origine (4 bit)
B: secondo registro sorgente o coppia (4 bit)
Eseguire l'operazione binaria identificata sui due registri sorgente, memorizzando il risultato nel primo registro sorgente.

Nota: contrariamente ad altre operazioni matematiche -long/2addr (che accettano coppie di registri sia per la loro destinazione/prima sorgente che per la loro seconda sorgente), shl-long/2addr , shr-long/2addr e ushr-long/2addr prendono un registro coppia per la loro destinazione/prima sorgente (il valore da spostare), ma un unico registro per la loro seconda sorgente (la distanza di spostamento).

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: e-int/lit16
d6: or-int/lit16
d7: xor-int/lit16
A: registro di destinazione (4 bit)
B: registro sorgente (4 bit)
C: costante int con segno (16 bit)
Eseguire 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 sua famiglia. Inoltre, vedi sotto per 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: e-int/lit8
de: or-int/lit8
df: xor-int/lit8
e0: shl-int/lit8
e1: sh-int/lit8
e2: ushr-int/lit8
A: registro di destinazione (8 bit)
B: registro sorgente (8 bit)
C: costante int con segno (8 bit)
Eseguire l'operazione binaria indicata sul registro indicato (primo argomento) e sul valore letterale (secondo argomento), memorizzando il risultato nel registro di destinazione.

Nota: vedi sotto per i dettagli sulla semantica di rsub-int .

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

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

Il ricevitore deve essere un oggetto che supporta il metodo polimorfico della firma richiamato.

Il riferimento al prototipo descrive i tipi di argomento forniti e il tipo restituito previsto.

Il bytecode invoke-polymorphic può sollevare eccezioni durante l'esecuzione. Le eccezioni sono descritte nella documentazione dell'API per il metodo polimorfico della firma richiamato.

Presente nei file Dex dalla versione 038 in poi.
fb 4rc invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH A: conteggio parole argomento (8 bit)
B: indice di riferimento del metodo (16 bit)
C: ricevitore (16 bit)
H: indice di riferimento prototipo (16 bit)
N = A + C - 1
Richiamare l'handle del metodo indicato. Per i dettagli, vedere la descrizione invoke-polymorphic sopra.

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

Questa istruzione viene eseguita in due fasi: risoluzione del sito di chiamata e chiamata al 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, viene richiamato il metodo del linker bootstrap per il sito di chiamata indicato utilizzando gli argomenti presenti nel file DEX (consultare call_site_item ). Il metodo del linker bootstrap restituisce un'istanza java.lang.invoke.CallSite che verrà quindi associata al sito di chiamata indicato se non esiste alcuna associazione. Un altro thread potrebbe aver già eseguito l'associazione per prima e, in tal caso, l'esecuzione dell'istruzione continua con la prima istanza java.lang.invoke.CallSite associata.

La chiamata al sito di chiamata viene eseguita sulla destinazione java.lang.invoke.MethodHandle dell'istanza java.lang.invoke.CallSite risolta. Il target viene richiamato come se eseguendo invoke-polymorphic (descritto sopra) utilizzando l'handle del metodo e gli argomenti dell'istruzione invoke-custom come argomenti per un'esatta invocazione dell'handle del metodo.

Le eccezioni sollevate dal metodo bootstrap linker sono racchiuse in un java.lang.BootstrapMethodError . Viene generato un BootstrapMethodError anche se:
  • il metodo del linker bootstrap non riesce a restituire un'istanza java.lang.invoke.CallSite .
  • java.lang.invoke.CallSite restituito ha una destinazione di handle del metodo null .
  • la destinazione dell'handle del metodo non è del tipo richiesto.
Presente nei file Dex dalla versione 038 in poi.
fd 3rc invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB A: conteggio parole argomento (8 bit)
B: indice di riferimento del sito di chiamata (16 bit)
C: registro del primo argomento (16 bit)
N = A + C - 1
Risolvi e richiama un sito di chiamata. Per i dettagli, vedere la descrizione invoke-custom sopra.

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

Presente nei file Dex dalla versione 039 in poi.
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 specificato nel registro specificato.

Presente nei file Dex dalla versione 039 in poi.

formato di carico utile dello switch compresso

Nome Formato Descrizione
ident ucorto = 0x0100 identificare lo pseudo-codice operativo
taglia corto numero di voci nella tabella
prima_chiave int valore del primo (e più basso) switch case
obiettivi int[] elenco di destinazioni ramo relative alle size . I target sono relativi all'indirizzo del codice operativo dello 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 ucorto = 0x0200 identificare lo pseudo-codice operativo
taglia corto numero di voci nella tabella
chiavi int[] elenco dei valori chiave della size , ordinati dal basso verso l'alto
obiettivi int[] elenco di target branch relativi alle size , ciascuno corrispondente al valore della chiave nello stesso indice. I target sono relativi all'indirizzo del codice operativo dello switch, non di questa tabella.

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

formato fill-array-data-payload

Nome Formato Descrizione
ident ucorto = 0x0300 identificare lo pseudo-codice operativo
larghezza_elemento corto numero di byte in ogni elemento
taglia uint numero di elementi nella tabella
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 operazioni matematiche

Nota: le operazioni in virgola mobile devono seguire le regole IEEE 754, utilizzando l'underflow arrotondato al più vicino e graduale, salvo diversamente indicato.

Codice operativo C semantica Appunti
neg-int int32 a;
int32 risultato = -a;
Complemento a due unario.
non-int int32 a;
int32 risultato = ~a;
Complemento unario.
neg-lungo int64 a;
int64 risultato = -a;
Complemento a due unario.
non molto int64 a;
int64 risultato = ~a;
Complemento unario.
neg-flottante galleggiante a;
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 .