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.
- 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
- 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'intervallov0
–v65535
. 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'istruzionenop
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'intervallov0
–v255
. - "
vBBBB
" è il registro di origine, che deve essere compreso nell'intervallov0
–v65535
.
- "
- 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 | |
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 |
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 |
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 |
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, |
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é |
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é |
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 taglieC: 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 |
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 |
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 testareB: "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 testareB: "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 coppiaC: 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 |
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 |
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 |
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. Quando Nei file Dex versione 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 |
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 |
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: |
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 |
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:
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 . |