Progettazione generale
- Il modello della 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 vengono fissate al momento della creazione. Ogni frame è costituito da un numero particolare di registri (specificati 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 . - Se 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 vi è alcun requisito di allineamento per le coppie di registri.
- Se utilizzati per riferimenti a oggetti, i registri sono considerati sufficientemente ampi da contenere esattamente uno di questi riferimenti.
- In termini di rappresentazione bit a bit,
(Object) null == (int) 0
. - Gli N argomenti di un metodo finiscono negli ultimi N registri del frame di invocazione del metodo, in ordine. Gli argomenti ampi consumano due registri. Ai metodi di istanza viene passato
this
riferimento come primo argomento.
- La macchina è basata su registri e le dimensioni dei frame vengono fissate al momento della creazione. Ogni frame è costituito da un numero particolare di registri (specificati 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 memorizzazione 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 numeri interi o float.
- Sono disponibili pool costanti enumerati e indicizzati separatamente per i riferimenti a stringhe, tipi, campi e metodi.
- I dati letterali bit a bit sono rappresentati in linea nel flusso di istruzioni.
- Poiché, in pratica, è raro che un metodo necessiti di 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 un numero di registri molto maggiore, inclusa una coppia di istruzioni
move
generali che possono indirizzare i registri nell'intervallov0
–v65535
. Nei casi in cui non è disponibile una variante dell'istruzione per indirizzare un registro desiderato, è previsto che il contenuto del registro venga spostato dal registro originale a un registro basso (prima dell'operazione) e/o spostato da un registro dei risultati basso a uno alto registrarsi (dopo l'operazione). - Esistono diverse "pseudo-istruzioni" utilizzate per contenere payload di dati di lunghezza variabile, a cui fanno riferimento 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 del 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 sarebbe altrimenti non allineata. Infine, sebbene non sia obbligatorio, ci si aspetta che la maggior parte degli strumenti scelga di emettere queste istruzioni alla fine dei metodi, poiché altrimenti sarebbe probabile che sarebbero necessarie istruzioni aggiuntive per ramificarsi attorno ad essi. - Quando vengono installate su un sistema in esecuzione, alcune istruzioni potrebbero essere alterate, cambiando il loro formato, come ottimizzazione del collegamento statico in fase di installazione. Questo per consentire un'esecuzione più rapida una volta noto il collegamento. Consultare il documento relativo ai formati delle istruzioni per le varianti suggerite. La parola "consigliato" è usata di proposito; non è obbligatorio implementarli.
- Sintassi umana e mnemonici:
- Ordinamento destinazione-quindi-origine per gli argomenti.
- Alcuni codici operativi hanno un suffisso del nome disambiguante per indicare il/i tipo/i su cui operano:
- I codici operativi di tipo generale a 32 bit non sono contrassegnati.
- I codici operativi di tipo generale a 64 bit hanno il suffisso
-wide
. - I codici operativi specifici del tipo hanno il suffisso con il loro tipo (o un'abbreviazione semplice), uno tra:
-boolean
-byte
-char
-short
-int
-long
-float
-double
-object
-string
-class
-void
.
- Alcuni codici operativi hanno un suffisso disambiguante per distinguere operazioni altrimenti identiche che hanno layout o opzioni di istruzioni diversi. Questi suffissi sono separati dai nomi principali con una barra ("
/
") e esistono principalmente per garantire una mappatura uno a uno con costanti statiche nel codice che genera e interpreta gli eseguibili (ovvero per ridurre l'ambiguità per gli esseri umani). - Nelle presenti descrizioni la larghezza di un valore (che indica ad esempio l'intervallo di una costante o il numero di registri eventualmente indirizzati) viene enfatizzata mediante l'utilizzo di un carattere ogni 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 (spostare 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 come sorgente un riferimento al registro a 16 bit. - "
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 sorgente, che deve essere compreso nell'intervallov0
–v65535
.
- "
- Consulta il documento sui formati delle istruzioni per maggiori dettagli sui vari formati delle istruzioni (elencati sotto "Op e formato") nonché dettagli sulla sintassi del codice operativo.
- Consulta il documento sul formato file
.dex
per maggiori dettagli su dove si inserisce il bytecode nel quadro più ampio.
Riepilogo del set di bytecode
Operazione 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 | spostare vA, vB | A: registro di destinazione (4 bit)B: registro sorgente (4 bit) | Sposta il contenuto di un registro non oggetto in un altro. |
0222x | 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. |
0332x | 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. |
0412x | movimento ampio 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 | spostamento in larghezza/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 |
0632x | spostamento in larghezza/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 |
0712x | 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/da16 vAA, vBBBB | A: registro di destinazione (8 bit)B: registro sorgente (16 bit) | Sposta il contenuto di un registro porta oggetti in un altro. |
0932x | 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 | risultato-movimento 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 (parola singola, non oggetto) non deve essere ignorato; altrove non è valido. |
0b11x | vAA a livello di risultato dello spostamento | A: coppia di registri di destinazione (8 bit) | Sposta il risultato della doppia parola del invoke- kind più recente nella coppia di registri indicata. Questo deve essere fatto come istruzione immediatamente dopo un invoke- kind il cui risultato (doppia parola) non deve essere ignorato; altrove non è valido. |
0c11x | oggetto-risultato-movimento vAA | A: registro di destinazione (8 bit) | Sposta il risultato dell'oggetto invoke- kind più recente nel registro indicato. Questo deve essere fatto come istruzione immediatamente dopo un invoke- kind filled-new-array il cui risultato (oggetto) non deve essere ignorato; altrove non è valido. |
0d 11x | eccezione di spostamento 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 sempre verificarsi solo come prima istruzione di un gestore di eccezioni; altrove non è valido. |
0e 10x | reso-nulla | Metodo di ritorno da un 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). |
1011x | vAA a livello di ritorno | A: coppia di registri del valore restituito (8 bit) | Restituzione da un metodo di restituzione del valore a doppia larghezza (64 bit). |
1111x | oggetto restituito vAA | A: registro del valore di ritorno (8 bit) | Restituzione da un metodo di restituzione di oggetti. |
12 11n | cost/4 vA, #+B | A: registro di destinazione (4 bit)B: con segno intero (4 bit) | Sposta il valore letterale specificato (segno esteso a 32 bit) nel registro specificato. |
13 21s | cost/16 vAA, #+BBBB | A: registro di destinazione (8 bit)B: con segno intero (16 bit) | Sposta il valore letterale specificato (segno esteso a 32 bit) nel registro specificato. |
14 31i | cost vAA, #+BBBBBBBB | A: registro di destinazione (8 bit)B: costante arbitraria a 32 bit | Sposta il valore letterale specificato nel registro specificato. |
15 21h | cost/alta16 vAA, #+BBBB0000 | A: registro di destinazione (8 bit)B: con segno intero (16 bit) | Sposta il valore letterale fornito (zero destro esteso a 32 bit) nel registro specificato. |
16 21 secondi | const-wide/16 vAA, #+BBBB | A: registro di destinazione (8 bit)B: con segno intero (16 bit) | Sposta il valore letterale fornito (segno esteso a 64 bit) nella coppia di registri specificata. |
17 31i | const-wide/32 vAA, #+BBBBBBBB | A: registro di destinazione (8 bit)B: con segno intero (32 bit) | Sposta il valore letterale fornito (segno esteso a 64 bit) nella coppia di registri specificata. |
18 51l | vAA a livello const, #+BBBBBBBBBBBBBBBB | A: registro di destinazione (8 bit)B: costante arbitraria a doppia larghezza (64 bit). | Sposta il valore letterale fornito nella coppia di registri specificata. |
19 21h | const-wide/high16 vAA, #+BBBB000000000000 | A: registro di destinazione (8 bit)B: con segno intero (16 bit) | Sposta il valore letterale fornito (zero destro esteso a 64 bit) nella coppia di registri specificata. |
1a21c | const-string vAA, stringa@BBBB | A: registro di destinazione (8 bit)B: indice di stringa | Sposta un riferimento alla stringa specificata dall'indice dato nel registro specificato. |
1b 31c | const-string/jumbo vAA, stringa@BBBBBBBB | A: registro di destinazione (8 bit)B: indice di stringa | Sposta un riferimento alla stringa specificata dall'indice dato nel registro specificato. |
1c 21c | vAA di classe const, tipo@BBBB | A: registro di destinazione (8 bit)B: indice del tipo | Sposta un riferimento alla classe specificata dall'indice dato nel registro specificato. Nel caso in cui il tipo indicato sia primitivo, verrà memorizzato un riferimento alla classe degenere del tipo primitivo. |
1d 11x | monitor-inserire vAA | A: registro del cuscinetto di riferimento (8 bit) | Ottieni il monitor per l'oggetto indicato. |
1e 11x | vAA di uscita dal monitor | A: registro del cuscinetto 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 avesse già superato l'istruzione. Potrebbe essere utile pensare a questo come all'esecuzione corretta dell'istruzione (in un certo senso) e all'eccezione che viene lanciata dopo l'istruzione ma prima che quella successiva abbia la possibilità di essere eseguita. Questa definizione rende possibile per un metodo utilizzare un blocco catch-all (ad esempio, |
1f 21c | controlla il cast di vAA, digita @BBBB | A: registro del cuscinetto di riferimento (8 bit)B: indice del tipo (16 bit) | Genera un'eccezione ClassCastException se il riferimento nel registro specificato non può essere convertito nel tipo indicato. Nota: poiché |
2022c | istanza di vA, vB, type@CCCC | A: registro di destinazione (4 bit)B: registro del riferimento (4 bit)C: indice del tipo (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 del cuscinetto di riferimento dell'array (4 bit) | Memorizza nel registro di destinazione specificato la lunghezza dell'array indicato, in voci |
2221c | vAA di nuova istanza, tipo@BBBB | A: registro di destinazione (8 bit)B: indice del tipo | Costruisce 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 | nuovo-array vA, vB, tipo@CCCC | A: registro di destinazione (4 bit)B: registro delle taglieC: tipo indice | Costruisci un nuovo array del tipo e della dimensione indicati. Il tipo deve essere un tipo di matrice. |
2435c | array-nuovo-riempito {vC, vD, vE, vF, vG}, tipo@BBBB | A: dimensione dell'array e conteggio delle parole degli argomenti (4 bit)B: indice del tipo (16 bit)C..G: registri degli argomenti (4 bit ciascuno) | Costruisci un array del tipo e della dimensione specificati, riempiendolo con il contenuto fornito. Il tipo deve essere un tipo di matrice. Il contenuto dell'array deve essere composto da una sola parola (ovvero, nessun array di long o double , ma i tipi di riferimento sono accettabili). L'istanza costruita viene memorizzata come un "risultato" nello stesso modo in cui le istruzioni di chiamata del 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 | array/intervallo nuovo-riempito {vCCCC .. vNNNN}, tipo@BBBB | A: dimensione dell'array e conteggio delle parole degli argomenti (8 bit)B: indice del tipo (16 bit)C: registro del primo argomento (16 bit)N = A + C - 1 | Costruisci un array del tipo e della dimensione specificati, riempiendolo con il contenuto fornito. Chiarimenti e restrizioni sono gli stessi filled-new-array , descritti sopra. |
26 31t | fill-array-data vAA, +BBBBBBBB (con dati supplementari come specificato di seguito nel "formato fill-array-data-payload ") | A: riferimento dell'array (8 bit)B: offset del "ramo" con segno rispetto alla pseudo-istruzione dei dati della tabella (32 bit) | Riempi l'array fornito con i dati indicati. Il riferimento deve essere a un array di primitive e la tabella dati deve corrispondere ad esso in termini di tipo e non deve contenere più elementi di quelli che possono essere inseriti 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. |
2711x | lancia vAA | A: registro delle eccezioni (8 bit) | Lancia l'eccezione indicata. |
28 10 t | vai a +AA | A: offset del ramo con segno (8 bit) | Passa incondizionatamente all'istruzione indicata. Nota: l'offset del ramo non deve essere |
29 20 t | vai a/16 +AAAA | A: offset del ramo con segno (16 bit) | Passa incondizionatamente all'istruzione indicata. Nota: l'offset del ramo non deve essere |
2a 30t | vai a/32 +AAAAAAAA | A: offset del ramo con segno (32 bit) | Passa incondizionatamente all'istruzione indicata. |
2b 31t | vAA con commutatore compresso, +BBBBBBBB (con dati supplementari come specificato di seguito nel "formato packed-switch-payload ") | A: registrati per testareB: offset del "ramo" con segno rispetto alla 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 nel "formato sparse-switch-payload ") | A: registrati per testareB: offset del "ramo" con segno rispetto alla 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 | cmp tipo vAA, vBB, vCC 2d: cmmpl-float (bias lt) 2e: cmpg-float (distorsione gt) 2f: cmmpl-double (lt bias) 30: cmpg-double (bias gt) 31: cmp-lungo | A: registro di destinazione (8 bit)B: primo registro o coppia sorgenteC: secondo registro o coppia sorgente | Eseguire il confronto long o in virgola mobile 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 in 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 del ramo con segno (16 bit) | Passa alla destinazione specificata se i valori dei due registri vengono confrontati 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 del ramo con segno (16 bit) | Salta alla destinazione data se il valore del registro dato confronta 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: età 45: a livello di età 46: oggetto-get 47: get-booleano 48: byte-get 49: get-char 4a: età-breve 4b: aput 4c: aput-wide 4d: oggetto-aput 4e: aput-booleano 4f: aput-byte 50: aput-char 51: aput-corto | A: registro o coppia di valori; può essere sorgente o destinazione (8 bit)B: registro array (8 bit)C: registro indice (8 bit) | Esegue l'operazione sull'array identificato sull'indice identificato dell'array specificato, caricando o memorizzando nel registro dei valori. |
52..5f 22c | i esempio di vA, vB, field@CCCC 52: iget 53: iget-wide 54: oggetto-iget 55: iget-booleano 56: iget-byte 57: iget-char 58: iget-corto 59: immesso 5a: a livello di iput 5b: oggetto iput 5c: iput-booleano 5d: iput-byte 5e: iput-car 5f: iput-breve | A: registro o coppia di valori; può essere sorgente o destinazione (4 bit)B: registro oggetti (4 bit)C: indice di riferimento del campo 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 per ottenere un offset più diretto. |
60..6d 21c | s statico vAA, campo@BBBB 60: sget 61: sget-wide 62: oggetto-sget 63: sget-booleano 64: sget-byte 65: sget-char 66: in breve 67: sputato 68: sput-wide 69: oggetto sput 6a: sput-booleano 6b: byte sput 6c: sput-char 6d: sputa corto | A: registro o coppia di valori; può essere sorgente o destinazione (8 bit)B: indice di riferimento del campo statico (16 bit) | Eseguire l'operazione del 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 per ottenere un offset più diretto. |
6e..72 35c | invoca- kind {vC, vD, vE, vF, vG}, meth@BBBB 6e: invoca-virtuale 6f: invoca-super 70: invocazione diretta 71: invoca-statico 72: interfaccia di invocazione | A: conteggio parole argomento (4 bit)B: indice di riferimento del metodo (16 bit)C..G: registri degli 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 il 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 essi). |
73 10x | (non utilizzato) | (non utilizzato) | |
74..78 3rc | invoke- kind /range {vCCCC .. vNNNN}, meth@BBBB 74: invoke-virtual/range 75: invoca-super/intervallo 76: invocazione diretta/intervallo 77: invoca-statico/intervallo 78: interfaccia/intervallo di invocazione | 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 prima descrizione invoke- kind sopra per dettagli, avvertenze e suggerimenti. |
79..7a 10x | (non utilizzato) | (non utilizzato) | |
7b..8f 12x | non op vA, vB 7b: neg-int 7c: non-int 7d: neg-lungo 7e: non lungo 7f: neg-float 80: neg-doppio 81: int-lungo 82: int-float 83: int-to-double 84: lungo-int 85: lungo da galleggiare 86: lungo al raddoppio 87: float-int 88: float-lungo 89: float-to-double 8a: doppio-int 8b: doppio-lungo 8c: double-float 8d: intero in byte 8e: int-car 8f: da intero a corto | A: registro o coppia di destinazione (4 bit)B: registro o coppia sorgente (4 bit) | Esegue l'operazione unaria identificata sul registro sorgente, memorizzando il risultato nel registro di destinazione. |
90..af 23x | binop vAA, vBB, vCC 90: add 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: shr-int 9a: ushr-int 9b: aggiungere-lungo 9c: sub-lungo 9d: molto lungo 9e: div lungo 9f: rem-lungo a0: e-lungo a1: o-lungo a2: xor-lungo a3: shl-lungo a4: breve a5: lunga un'ora a6: aggiungi-virgola mobile a7: sottogalleggiante a8: mul-float a9: div-float aa: rem-flottante ab: aggiungi-doppio ac: sub-doppio annuncio: mul-doppio ae: div-doppio af: rem-doppio | A: registro o coppia di destinazione (8 bit)B: primo registro o coppia sorgente (8 bit)C: secondo registro o coppia sorgente (8 bit) | Eseguire l'operazione binaria identificata sui due registri sorgente, 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/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-lungo/2addr bd: mul-lungo/2addr essere: div-lungo/2addr bf: rem-lungo/2addr c0: e-lungo/2addr c1: or-lungo/2addr c2: xor-lungo/2addr c3: shl-lungo/2addr c4: shr-lungo/2addr c5: ushr-long/2addr c6: aggiungi-float/2addr c7: sub-float/2addr c8: mul-float/2addr c9: div-float/2addr ca: rem-float/2addr cb: aggiungi-doppio/2addr cc: sub-doppio/2addr cd: mul-doppio/2addr ce: div-doppio/2addr cf: rem-double/2addr | A: destinazione e primo registro o coppia di origine (4 bit)B: secondo registro o coppia sorgente (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: and-int/lit16 d6: or-int/lit16 d7: xor-int/lit16 | A: registro di destinazione (4 bit)B: registro sorgente (4 bit)C: costante con segno intero (16 bit) | Esegue 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: 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 sorgente (8 bit)C: costante con segno intero (8 bit) | Esegue l'operazione binaria indicata sul registro indicato (primo argomento) e sul valore letterale (secondo argomento), memorizzando il risultato nel registro di destinazione. Nota: vedere 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 degli argomenti (4 bit ciascuno)H: indice di riferimento del 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 un metodo polimorfico della firma, come java.lang.invoke.MethodHandle.invoke o java.lang.invoke.MethodHandle.invokeExact .Il ricevitore deve essere un oggetto che supporta il metodo polimorfico della firma invocato. Il riferimento al prototipo descrive i tipi di argomenti 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. |
fb4rcc | invoca-polimorfico/intervallo {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 del prototipo (16 bit)N = A + C - 1 | Richiamare l'handle del metodo indicato. Vedi la descrizione invoke-polymorphic sopra per i dettagli.Presente nei file Dex dalla versione 038 in poi. |
FC 35c | richiama-personalizzato {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 degli argomenti (4 bit ciascuno) | Risolve e richiama il sito di chiamata indicato. Il risultato dell'invocazione (se presente) può essere memorizzato con una variante move-result* appropriata come istruzione immediatamente successiva.Questa istruzione viene eseguita in due fasi: risoluzione del sito di chiamata e invocazione del sito di chiamata. La risoluzione del sito di chiamata controlla se il sito di chiamata indicato ha un'istanza java.lang.invoke.CallSite associata. In caso contrario, il metodo del linker bootstrap per il sito di chiamata indicato viene richiamato utilizzando gli argomenti presenti nel file DEX (vedere 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à effettuato l'associazione per primo 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 effettuata sulla destinazione java.lang.invoke.MethodHandle dell'istanza java.lang.invoke.CallSite risolta. La destinazione viene invocata come se si stesse eseguendo invoke-polymorphic (descritto sopra) utilizzando l'handle del metodo e gli argomenti dell'istruzione invoke-custom come argomenti per l'esatta invocazione della gestione del metodo.Le eccezioni sollevate dal metodo del linker bootstrap sono racchiuse in un java.lang.BootstrapMethodError . Viene inoltre sollevato un BootstrapMethodError 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 | Risolvere e richiamare 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-metodo-handle vAA, metodo_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 fornito nel registro specificato. Presente nei file Dex dalla versione 039 in poi. |
ff 21c | vAA di tipo metodo const, 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 dalla versione 039 in poi. |
formato di carico utile di commutazione compresso
Nome | Formato | Descrizione |
---|---|---|
ident | ucorto = 0x0100 | identificare lo pseudo-codice operativo |
misurare | breve | numero di voci nella tabella |
prima_chiave | int | primo (e più basso) valore del caso di commutazione |
obiettivi | int[] | elenco di obiettivi di filiale relativi size . Gli obiettivi 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 di carico utile sparse-switch
Nome | Formato | Descrizione |
---|---|---|
ident | ucorto = 0x0200 | identificare lo pseudo-codice operativo |
misurare | breve | numero di voci nella tabella |
chiavi | int[] | elenco di valori chiave size , ordinati dal più basso al più alto |
obiettivi | int[] | elenco di obiettivi di ramo relativi size , ciascuno corrispondente al valore della chiave nello stesso indice. Gli obiettivi 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 | breve | numero di byte in ciascun elemento |
misurare | 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 dell'operazione matematica
Nota: le operazioni in virgola mobile devono seguire le regole IEEE 754, utilizzando il round-to-neest e l'underflow graduale, salvo diversa indicazione.
Codice operativo | Semantica C | Appunti |
---|---|---|
neg-int | int32a; risultato int32 = -a; | Complemento a due unario. |
non-int | int32a; risultato int32 = ~a; | Complemento a uno unario. |
neg-lungo | int64a; risultato int64 = -a; | Complemento a due unario. |
non molto tempo | int64a; risultato int64 = ~a; | Complemento a uno unario. |
neg-float | galleggiare a; risultato float = -a; | Negazione in virgola mobile. |
neg-doppio | doppia a; doppio risultato = -a; | Negazione in virgola mobile. |
int-to-long | int32a; risultato int64 = (int64) a; | Firma l'estensione di int32 in int64 . |
int-float | int32a; risultato float = (float) a; | Conversione di int32 in float , utilizzando round-to-nearest. Ciò perde precisione per alcuni valori. |
int-to-double | int32a; doppio risultato = (doppio) a; | Conversione di int32 in double . |
lungo-int | int64a; risultato int32 = (int32) a; | Troncamento di int64 in int32 . |
lungo per galleggiare | int64a; risultato float = (float) a; | Conversione di int64 in float , utilizzando round-to-nearest. Ciò perde precisione per alcuni valori. |
lungo da raddoppiare | int64a; doppio risultato = (doppio) a; | Conversione di int64 in double , utilizzando round-to-nearest. Ciò perde precisione per alcuni valori. |
float-int | galleggiare a; risultato int32 = (int32) a; | Conversione di float in int32 , utilizzando round-toward-zero. NaN e -0.0 (zero negativo) vengono convertiti nell'intero 0 . Gli infiniti e i valori con una grandezza troppo grande per essere rappresentati vengono convertiti in 0x7fffffff o -0x80000000 a seconda del segno. |
float-to-long | galleggiare a; risultato int64 = (int64) a; | Conversione di float in int64 , utilizzando round-toward-zero. Qui si applicano le stesse regole dei casi speciali di 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 | galleggiare a; doppio risultato = (doppio) a; | Conversione di float in double , preservando esattamente il valore. |
doppio-int | doppia a; risultato int32 = (int32) a; | Conversione di double in int32 , utilizzando round-toward-zero. Qui si applicano le stesse regole dei casi speciali valide per float-to-int . |
doppio-lungo | doppia a; risultato int64 = (int64) a; | Conversione di double in int64 , utilizzando round-toward-zero. Qui si applicano le stesse regole per i casi speciali valide per float-to-long . |
double-float | doppia a; risultato float = (float) a; | Conversione di double in float , utilizzando round-to-nearest. Ciò perde precisione per alcuni valori. |
int-byte | int32a; risultato int32 = (a << 24) >> 24; | Troncamento di int32 in int8 , segno che estende il risultato. |
int-char | int32a; risultato int32 = a & 0xffff; | Troncamento di int32 in uint16 , senza estensione del segno. |
da int a breve | int32a; risultato int32 = (a << 16) >> 16; | Troncamento di int32 in int16 , segno che estende il risultato. |
add | int32 a, b; risultato int32 = a + b; | Addizione in complemento a due. |
sub-int | int32 a, b; risultato int32 = a - b; | Sottrazione in complemento a due. |
rsub-int | int32 a, b; risultato int32 = b - a; | Sottrazione inversa in complemento a due. |
mul-int | int32 a, b; risultato int32 = a * b; | Moltiplicazione in complemento a due. |
div-int | int32 a, b; risultato int32 = a/b; | Divisione in complemento a due, arrotondata allo zero (cioè troncata all'intero). Questo lancia ArithmeticException se b == 0 . |
rem-int | int32 a, b; risultato int32 = a% b; | Resto in complemento a due della divisione. Il segno del risultato è lo stesso di a , e più precisamente è definito come result == a - (a / b) * b . Questo lancia ArithmeticException se b == 0 . |
e-int | int32 a, b; risultato int32 = a&b; | AND bit per bit. |
o-int | int32 a, b; risultato int32 = a | B; | OR bit per bit. |
xor-int | int32 a, b; risultato int32 = a ^ b; | XOR bit a bit. |
shl-int | int32 a, b; risultato int32 = a << (b & 0x1f); | Spostamento bit per bit a sinistra (con argomento mascherato). |
shr-int | int32 a, b; risultato int32 = a >> (b & 0x1f); | Spostamento a destra con segno bit per bit (con argomento mascherato). |
ushr-int | uint32 a, b; risultato int32 = a >> (b & 0x1f); | Spostamento a destra senza segno bit per bit (con argomento mascherato). |
aggiungere-lungo | int64 a, b; risultato int64 = a + b; | Addizione in complemento a due. |
sub-lungo | int64 a, b; risultato int64 = a - b; | Sottrazione in complemento a due. |
molto lungo | int64 a, b; risultato int64 = a * b; | Moltiplicazione in complemento a due. |
div-lungo | int64 a, b; int64 risultato = a/b; | Divisione in complemento a due, arrotondata allo zero (cioè troncata all'intero). Questo lancia ArithmeticException se b == 0 . |
rem-lungo | int64 a, b; risultato int64 = a% b; | Resto in complemento a due della divisione. Il segno del risultato è lo stesso di a , e più precisamente è definito come result == a - (a / b) * b . Questo lancia ArithmeticException se b == 0 . |
e-lungo | int64 a, b; risultato int64 = a&b; | AND bit per bit. |
o-lungo | int64 a, b; int64 risultato = a | B; | OR bit per bit. |
xor-lungo | int64 a, b; risultato int64 = a ^ b; | XOR bit per bit. |
shl-lungo | int64a; int32b; risultato int64 = a << (b & 0x3f); | Spostamento bit per bit a sinistra (con argomento mascherato). |
molto lungo | int64a; int32b; risultato int64 = a >> (b & 0x3f); | Spostamento a destra con segno bit per bit (con argomento mascherato). |
un'ora | uint64a; int32b; risultato int64 = a >> (b & 0x3f); | Spostamento a destra senza segno bit per bit (con argomento mascherato). |
aggiungi-float | float a, b; risultato float = a + b; | Addizione in virgola mobile. |
sottogalleggiante | float a, b; risultato float = a - b; | Sottrazione in virgola mobile. |
mul-float | float a, b; risultato float = a * b; | Moltiplicazione in virgola mobile. |
div-float | float a, b; risultato float = a/b; | Divisione in virgola mobile. |
rem-float | float a, b; risultato float = 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 . |
aggiungi-doppio | doppio a, b; doppio risultato = a + b; | Addizione in virgola mobile. |
sub-doppio | doppio a, b; doppio risultato = a - b; | Sottrazione in virgola mobile. |
mul-doppio | doppio a, b; doppio risultato = a*b; | Moltiplicazione in virgola mobile. |
div-doppio | doppio a, b; doppio risultato = a/b; | Divisione in virgola mobile. |
rem-doppio | doppio a, b; doppio risultato = 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 . |