Design generale
- Il modello di macchina e le convenzioni di chiamata hanno lo scopo di imitare approssimativamente le architetture reali comuni e le convenzioni di chiamata in stile C:
- La macchina è basata su registri e le dimensioni dei frame sono fisse al momento della creazione.
Ogni frame è costituito da un determinato numero di registri (specificati dal metodo) e da eventuali dati aggiuntivi necessari per l'esecuzione del metodo, come (a titolo esemplificativo) il contatore del programma e un riferimento al file
.dex
contenente il metodo. - Se utilizzati per valori in bit (ad esempio numeri interi e in virgola mobile), i registri sono considerati di 32 bit. Per i valori a 64 bit vengono utilizzate coppie di registri adiacenti. Non è richiesto alcun requisito di allineamento per le coppie di registri.
- Se utilizzati per i riferimenti agli oggetti, i registri sono considerati sufficientemente ampi per contenere esattamente un riferimento di questo tipo.
- In termini di rappresentazione a bit,
(Object) null == (int) 0
. - Gli N argomenti di un metodo vengono inseriti nell'ordine negli ultimi N registri del frame di chiamata del metodo. Gli argomenti ampi occupano
due registri. Ai metodi di istanza viene passato un riferimento
this
come primo argomento.
- La macchina è basata su registri e le dimensioni dei frame sono fisse al momento della creazione.
Ogni frame è costituito da un determinato numero di registri (specificati dal metodo) e da eventuali dati aggiuntivi necessari per l'esecuzione del metodo, come (a titolo esemplificativo) il contatore del programma e un riferimento al file
- L'unità di archiviazione nello stream di istruzioni è una quantità non firmata di 16 bit. Alcuni bit in alcune istruzioni vengono ignorati / devono essere pari a zero.
- Le istruzioni non sono limitate inutilmente a un determinato tipo. Ad esempio, le istruzioni che spostano i valori dei registri a 32 bit senza interpretazione non devono specificare se stanno spostando interi o valori in virgola mobile.
- Esistono pool di costanti enumerati e indicizzati separatamente per i riferimenti a stringhe, tipi, campi e metodi.
- I dati letterali a livello di bit sono rappresentati in linea nello stream di istruzioni.
- Poiché, in pratica, è raro che un metodo abbia bisogno di più di 16 registri e poiché la necessità di più di otto registri è ragionevolmente comune, molte istruzioni sono limitate all'indirizzamento solo dei primi 16 registri. Ove ragionevolmente possibile, le istruzioni consentono di fare riferimento fino ai primi 256 registri. Inoltre, alcune istruzioni hanno varianti
che consentono conteggi di registri molto più grandi, inclusa una coppia di istruzioni
move
generiche che possono indirizzare i registri nell'intervallov0
-v65535
. Nei casi in cui non sia disponibile una variante di istruzione per indirizzare un registro desiderato, è previsto che i contenuti del registro vengano spostati dal registro originale a un registro basso (prima dell'operazione) e/o da un registro del risultato basso a un registro alto (dopo l'operazione). - Esistono diverse "pseudo-istruzioni" utilizzate per memorizzare payload di dati di lunghezza variabile, a cui fanno riferimento le istruzioni regolari (ad esempio
fill-array-data
). Queste istruzioni non devono mai essere incontrate durante il normale flusso di esecuzione. Inoltre, le istruzioni devono trovarsi su offset del bytecode con numeri pari (ovvero allineati a 4 byte). Per soddisfare questo requisito, gli strumenti di generazione di dex devono emettere un'istruzionenop
aggiuntiva come separatore se questa istruzione non fosse allineata. Infine, anche se non è obbligatorio, è previsto che la maggior parte degli strumenti scelga di emettere queste istruzioni alla fine dei metodi, poiché in caso contrario è probabile che siano necessarie istruzioni aggiuntive per eseguire il branching. - Quando vengono installate su un sistema in esecuzione, alcune istruzioni potrebbero essere alterate, cambiandone il formato, come ottimizzazione del collegamento statico in fase di installazione. In questo modo, l'esecuzione sarà più rapida una volta noto il collegamento. Consulta il documento relativo ai formati didattici associato per le varianti suggerite. La parola "suggerito" è usata con cautela; non è obbligatorio implementarli.
- Sintassi e mnemoni simili a quelle umane:
- Ordine destinazione-poi-origine per gli argomenti.
- Alcuni opcode hanno un suffisso del nome per distinguere i tipi su cui operano:
- Le opzioni di codice di 32 bit di tipo generale non sono contrassegnate.
- Le opzioni di codice a 64 bit di tipo generico hanno il suffisso
-wide
. - Le opzioni di codice macchina specifiche per tipo sono seguite dal loro tipo (o da un'abbreviazione semplice), uno dei seguenti:
-boolean
-byte
-char
-short
-int
-long
-float
-double
-object
-string
-class
-void
.
- Alcuni opcode hanno un suffisso per distinguere operazioni apparentemente identiche che hanno layout o opzioni di istruzioni diversi. Questi suffissi sono separati dai nomi principali da una barra diagonale
("
/
") ed esistono principalmente per creare un mappatura uno a uno con costanti statiche nel codice che genera e interpreta gli eseguibili (ovvero per ridurre l'ambiguità per le persone). - Nelle descrizioni riportate di seguito, la larghezza di un valore (che indica, ad esempio, l'intervallo di una costante o il numero di registri eventualmente indirizzati) è evidenziata dall'uso di un carattere per quattro bit di larghezza.
- Ad esempio, nell'istruzione
"
move-wide/from16 vAA, vBBBB
":- "
move
" è l'opcode di base, che indica l'operazione di base (sposta il valore di un registro). - "
wide
" è il suffisso del nome, che indica che opera su dati ampi (64 bit). - "
from16
" è il suffisso dell'opcode, che indica una variante che ha un riferimento a un registro a 16 bit come origine. - "
vAA
" è il registro di destinazione (implicito nell'operazione; di nuovo, la regola è che gli argomenti di destinazione vengono sempre prima), che deve essere compreso nell'intervallov0
-v255
. - "
vBBBB
" è il registro di origine, che deve rientrare nell'intervallov0
-v65535
.
- "
- Consulta il documento relativo ai formati delle istruzioni per ulteriori dettagli sui vari formati delle istruzioni (elencati in "Op & Format") e sulla sintassi dell'opcode.
- Per ulteriori dettagli su dove si inserisce il bytecode nel quadro più ampio, consulta il documento sul formato del file
.dex
.
Riepilogo dell'insieme di bytecode
Op & Format | Mnemonico / sintassi | Argomenti | Descrizione |
---|---|---|---|
00 10x | nop | Cicli di rifiuti.
Nota:
le pseudo-istruzioni contenenti dati sono contrassegnate con questo codice operativo, nel qual caso il byte di ordine superiore dell'unità di codice operativo indica la natura dei dati. Consulta le sezioni "Formato |
|
01 12x | move vA, vB | A: registro di destinazione (4 bit)B: registro di origine (4 bit) |
Sposta i contenuti di un registro non oggetto in un altro. |
02 22x | move/from16 vAA, vBBBB | A: registro di destinazione (8 bit)B: registro di origine (16 bit) |
Sposta i contenuti di un registro non oggetto in un altro. |
03 32x | move/16 vAAAA, vBBBB | A: registro di destinazione (16 bit)B: registro di origine (16 bit) |
Sposta i contenuti di un registro non oggetto in un altro. |
04 12x | move-wide vA, vB | A: coppia di registri di destinazione (4 bit)B: coppia di registri di origine (4 bit) |
Sposta i contenuti di una coppia di registri in un'altra.
Nota:
è consentito passare da |
05 22x | move-wide/from16 vAA, vBBBB | A: Coppia di registri di destinazione (8 bit)B: Coppia di registri di origine (16 bit) |
Sposta i contenuti di una coppia di registri in un'altra.
Nota:
le considerazioni sull'implementazione sono le stesse di |
06 32x | move-wide/16 vAAAA, vBBBB | A: Coppia di registri di destinazione (16 bit)B: Coppia di registri di origine (16 bit) |
Sposta i contenuti di una coppia di registri in un'altra.
Nota:
le considerazioni sull'implementazione sono le stesse di |
07 12x | move-object vA, vB | A: registro di destinazione (4 bit)B: registro di origine (4 bit) |
Sposta i contenuti di un registro contenente oggetti in un altro. |
08 22x | move-object/from16 vAA, vBBBB | A: registro di destinazione (8 bit)B: registro di origine (16 bit) |
Sposta i contenuti di un registro contenente oggetti in un altro. |
09 32x | move-object/16 vAAAA, vBBBB | A: registro di destinazione (16 bit)B: registro di origine (16 bit) |
Sposta i contenuti di un registro contenente oggetti in un altro. |
0a 11x | move-result vAA | A: registro di destinazione (8 bit) |
Sposta il risultato non oggetto di una sola parola del invoke-kind più recente nel registro indicato.
Questo deve essere fatto come istruzione immediatamente dopo un
invoke-kind il cui risultato (una parola, non un oggetto)
non deve essere ignorato; in qualsiasi altro punto non è valido. |
0b 11x | move-result-wide vAA | Coppia di registri di destinazione A: (8 bit) |
Sposta il risultato a due parole dell'invoke-kind più recente nella coppia di registri indicata.
Questa istruzione deve essere eseguita immediatamente dopo un
invoke-kind il cui risultato (a due parole)
non deve essere ignorato; in qualsiasi altro punto non è valida. |
0c 11x | move-result-object vAA | A: registro di destinazione (8 bit) |
Sposta il risultato dell'oggetto dell'invoke-kind
più recente nel registro indicato. Questa istruzione deve essere eseguita immediatamente dopo un invoke-kind o un filled-new-array il cui risultato (oggetto) non deve essere ignorato. In qualsiasi altro punto non è valida. |
0d 11x | move-exception vAA | A: registro di destinazione (8 bit) |
Salva un'eccezione appena rilevata nel registro specificato. Deve essere la prima istruzione di qualsiasi gestore delle eccezioni la cui eccezione rilevata non deve essere ignorata e deve verificarsi soltanto come prima istruzione di un gestore delle eccezioni. In qualsiasi altro punto non è valida. |
0 e 10 volte | return-void | Torna da un metodo void . |
|
0 di 11x | return vAA | Registro del valore restituito A: (8 bit) |
Ritorna da un metodo che restituisce un valore non oggetto di larghezza singola (32 bit). |
10 11x | vAA a livello di ritorno | A: coppia di registri del valore restituito (8 bit) |
Ritorna da un metodo che restituisce un valore a doppia larghezza (64 bit). |
11 11x | return-object vAA | Registro del valore restituito A: (8 bit) |
Ritorna da un metodo che restituisce un oggetto. |
12 11n | const/4 vA, #+B | A: registro di destinazione (4 bit)B: int firmato (4 bit) |
Sposta il valore letterale specificato (con segno esteso a 32 bit) nel registro specificato. |
13 21 | const/16 vAA, #+BBBB | A: registro di destinazione (8 bit)B: int con segno (16 bit) |
Sposta il valore della stringa specificato (con segno esteso a 32 bit) nel registro specificato. |
14 31i | const vAA, #+BBBBBBBB | A: registro di destinazione (8 bit)B: costante arbitraria a 32 bit |
Sposta il valore letterale specificato nel registro specificato. |
15 21h | const/high16 vAA, #+BBBB0000 | A: registro di destinazione (8 bit)B: int con segno (16 bit) |
Sposta il valore letterale specificato (esteso a 32 bit a destra con zero) nel registro specificato. |
16 21 | const-wide/16 vAA, #+BBBB | A: registro di destinazione (8 bit)B: int con segno (16 bit) |
Sposta il valore letterale specificato (con segno esteso a 64 bit) nella coppia di registri specificata. |
17 31i | const-wide/32 vAA, #+BBBBBBBB | A: registro di destinazione (8 bit)B: int firmato (32 bit) |
Sposta il valore letterale specificato (con segno esteso a 64 bit) nella coppia di registri specificata. |
18 51l | const-wide vAA, #+BBBBBBBBBBBBBBBB | A: registro di destinazione (8 bit)B: costante arbitraria a doppia larghezza (64 bit) |
Sposta il valore letterale specificato nella coppia di registri specificata. |
19 21h | const-wide/high16 vAA, #+BBBB000000000000 | A: registro di destinazione (8 bit)B: int con segno (16 bit) |
Sposta il valore letterale specificato (esteso a destra a 64 bit) nella coppia di registri specificata. |
1a 21c | const-string vAA, string@BBBB | A: registro di destinazione (8 bit)B: indice di stringa |
Sposta un riferimento alla stringa specificata dall'indice specificato nel registro specificato. |
1b 31c | const-string/jumbo vAA, string@BBBBBBBB | A: registro di destinazione (8 bit)B: indice di stringa |
Sposta un riferimento alla stringa specificata dall'indice specificato nel registro specificato. |
1c 21c | const-class vAA, type@BBBB | A: registro di destinazione (8 bit)B: indice di tipo |
Sposta un riferimento alla classe specificata dall'indice specificato nel registro specificato. Se il tipo indicato è primitivo, verrà memorizzato un riferimento alla classe degenere del tipo primitivo. |
1 giorno 11x | monitor-enter vAA | A: registro con riferimento (8 bit) |
Acquisisci il monitor per l'oggetto indicato. |
1e 11x | monitor-exit vAA | A: registro con riferimento (8 bit) |
Rilascia il monitoraggio per l'oggetto indicato.
Nota:
se questa istruzione deve generare un'eccezione, deve farlo come se il PC avesse già superato l'istruzione.
Potrebbe essere utile pensare che l'istruzione venga eseguita correttamente (in un certo senso) e che l'eccezione venga lanciata dopo l'istruzione, ma prima che l'istruzione successiva abbia la possibilità di essere eseguita. Questa definizione consente a un metodo di utilizzare un valore generico per la pulizia del monitor (ad es. |
1f 21c | check-cast vAA, type@BBBB | A: registro di riferimento (8 bit)B: indice di tipo (16 bit) |
Lancia un ClassCastException se il riferimento nel
register specificato non può essere sottoposto a conversione al tipo indicato.
Nota: poiché |
20 22c | instance-of vA, vB, type@CCCC | A: registro di destinazione (4 bit)B: registro di riferimento (4 bit)C: indice di tipo (16 bit) |
Memorizza nel registro di destinazione specificato 1
se il riferimento indicato è un'istanza del tipo specificato,
oppure 0 in caso contrario.
Nota: poiché |
21 12x | array-length vA, vB | A: registro di destinazione (4 bit)B: registro contenente il riferimento all'array (4 bit) |
Memorizza nel registro di destinazione specificato la lunghezza dell'array indicato, in voci |
22 21c | new-instance vAA, type@BBBB | A: registro di destinazione (8 bit)B: indice di tipo |
Costruisci una nuova istanza del tipo indicato, memorizzando un riferimento nella destinazione. Il tipo deve fare riferimento a una classe non array. |
23 22c | new-array vA, vB, type@CCCC | A: registro di destinazione (4 bit)B: registro della dimensioneC: indice del tipo |
Costruisci un nuovo array del tipo e delle dimensioni indicati. Il tipo deve essere un tipo di array. |
24 35c | array-nuovo-completo {vC, vD, vE, vF, vG}, tipo@BBBB |
A: dimensione dell'array e numero di parole degli argomenti (4 bit)B: indice di tipo (16 bit)C..G: registri degli argomenti (4 bit ciascuno)
|
Costruisci un array del tipo e delle dimensioni specificati, riempiendolo con i contenuti forniti. Il tipo deve essere un tipo di array. I contenuti
dell'array devono essere costituiti da una sola parola (ovvero
non devono essere presenti array di long o double , ma sono accettabili i tipi di riferimento). L'istanza costruita viene memorizzata come "risultato" nello stesso modo in cui le istruzioni di chiamata del metodo memorizzano i risultati, pertanto l'istanza costruita deve essere spostata in un registro con un'istruzione move-result-object immediatamente successiva (se deve essere utilizzata). |
25 3rc | array/intervallo nuovo e completo {vCCCC .. vNNNN}, tipo@BBBB | A: dimensione dell'array e numero di parole dell'argomento (8 bit)B: indice di tipo (16 bit)C: registro primo argomento (16 bit)N = A + C - 1 |
Costruisci un array del tipo e delle dimensioni specificati, compilandolo con
i contenuti forniti. I chiarimenti e le limitazioni sono gli stessi
di filled-new-array , descritti sopra. |
26 31t | fill-array-data vAA, +BBBBBBBB (con i dati supplementari specificati
di seguito in "Formato fill-array-data-payload ") |
A: Riferimento all'array (8 bit)B: Pseudo-istruzione di offset "branch" firmato ai dati della tabella
(32 bit)
|
Compila l'array specificato con i dati indicati. Il riferimento deve essere a un array di elementi primitivi e la tabella di dati deve avere lo stesso tipo e non deve contenere più elementi di quelli che possono essere inseriti nell'array. In altre parole, l'array potrebbe essere più grande della tabella e, in questo caso, vengono impostati solo gli elementi iniziali dell'array, lasciando invariato il resto. |
27 11x | throw vAA | A: registro con eccezioni (8 bit) |
Genera l'eccezione indicata. |
28 10t | goto +AA | A: offset del ramo con segno (8 bit) |
Passa incondizionatamente all'istruzione indicata.
Nota:
l'offset del ramo non deve essere |
29 20t | goto/16 +AAAA | A: offset del ramo con segno (16 bit) |
Passa incondizionatamente all'istruzione indicata.
Nota:
l'offset del ramo non deve essere |
2a 30t | goto/32 +AAAAAAAA | A: offset del ramo con segno (32 bit) |
Passa incondizionatamente all'istruzione indicata. |
2b 31t | packed-switch vAA, +BBBBBBBB (con dati supplementari come
specificato di seguito in "Formato packed-switch-payload ") |
A: register to testB: offset "branch" firmato per pseudo-istruzione di dati di tabella
(32 bit)
|
Passa a una nuova istruzione in base al valore nel registro specificato, utilizzando una tabella di offset corrispondenti a ciascun valore in un determinato intervallo di numeri interi, oppure passa all'istruzione successiva se non c'è corrispondenza. |
2c 31t | sparse-switch vAA, +BBBBBBBB (con dati supplementari come
specificato di seguito in "Formato sparse-switch-payload ") |
A: register to testB: offset "branch" firmato per pseudo-istruzione di dati di tabella
(32 bit)
|
Vai a una nuova istruzione in base al valore nel registro specificato, utilizzando una tabella ordinata di coppie di valori e offset oppure vai all'istruzione successiva se non c'è corrispondenza. |
2d..31 23x | cmpkind vAA, vBB, vCC 2d: cmpl-float (lt bias) 2e: cmpg-float (gt bias) 2f: cmpl-double (lt bias) 30: cmpg-double (gt bias) 31: cmp-long |
A: registro di destinazione (8 bit)B: prima coppia o primo registro di origineC: seconda coppia o secondo registro di origine |
Esegui il confronto indicato con numeri in virgola mobile o long , impostando a su 0 se b == c , su 1 se b > c o su -1 se b < c .
Il "bias" elencato per le operazioni in virgola mobile indica come vengono trattati i confronti NaN : le istruzioni "gt bias" restituiscono 1 per i confronti NaN , mentre le istruzioni "lt bias" restituiscono -1 .
Ad esempio, per verificare se il numero in virgola mobile è uguale a |
32..37 22t | if-test vA, vB, +CCCC 32: if-eq 33: if-ne 34: if-lt 35: if-ge 36: if-gt 37: if-le |
A: primo registro da testare (4 bit)B: secondo registro da testare (4 bit)C: offset del ramo con segno (16 bit) |
Esegui il branch alla destinazione specificata se i valori dei due registri specificati
corrispondono come specificato.
Nota:
l'offset del ramo non deve essere |
38..3d 21t | if-testz vAA, +BBBB 38: if-eqz 39: if-nez 3a: if-ltz 3b: if-gez 3c: if-gtz 3d: if-lez |
A: registro per il test (8 bit)B: offset del ramo con segno (16 bit) |
Esegui il branch alla destinazione specificata se il valore del registro specificato viene confrontato con 0 come specificato.
Nota:
l'offset del ramo non deve essere |
3e..43 10x | (non utilizzato) | (non utilizzato) | |
44..51 23x | arrayop vAA, vBB, vCC 44: aget 45: aget-wide 46: aget-object 47: aget-boolean 48: aget-byte 49: aget-char 4a: aget-short 4b: aput 4c: aput-wide 4d: aput-object 4e: aput-boolean 4f: aput-byte 50: aput-char 51: aput-short |
A: registro o coppia di valori; può essere di origine o di destinazione
(8 bit)B: registro array (8 bit)C: registro di indice (8 bit) |
Esegui l'operazione sull'array identificata nell'indice identificato della matrice specificata, caricando o memorizzando nel registro dei valori. |
52,5 f 22 °C | iinstanceop vA, vB, field@CCCC 52: iget 53: iget-wide 54: iget-object 55: iget-boolean 56: iget-byte 57: iget-char 58: iget-short 59: iput 5a: iput-wide 5b: iput-object 5c: iput-boolean 5d: iput-byte 5e: iput-char 5f: iput-short |
A: registro o coppia di valori; può essere source o dest
(4 bit)B: registro oggetto (4 bit)C: indice di riferimento del campo dell'istanza (16 bit) |
Esegui l'operazione sul campo dell'istanza dell'oggetto identificato con il campo identificato, caricandolo o memorizzandolo nel registro dei valori.
Nota: questi opcode sono candidati ragionevoli per il collegamento statico, modificando l'argomento del campo in modo che sia un offset più diretto. |
60..6d 21c | sstaticop vAA, field@BBBB 60: sget 61: sget-wide 62: sget-object 63: sget-boolean 64: sget-byte 65: sget-char 66: sget-short 67: sput 68: sput-wide 69: sput-object 6a: sput-boolean 6b: sput-byte 6c: sput-char 6d: sput-short |
A: registro o coppia di valori; può essere source o dest
(8 bit)B: indice di riferimento del campo statico (16 bit) |
Esegui l'operazione sul campo statico dell'oggetto identificato con il campo statico identificato, caricandolo o memorizzandolo nel registro del valore.
Nota: questi opcode sono candidati ragionevoli per il collegamento statico, modificando l'argomento del campo in modo che sia un offset più diretto. |
6e..72 35c | invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB 6e: invoke-virtual 6f: invoke-super 70: invoke-direct 71: invoke-static 72: invoke-interface |
A: numero di parole dell'argomento (4 bit)B: indice di riferimento al metodo (16 bit)C..G: registri degli argomenti (4 bit ciascuno)
|
Chiama il metodo indicato. Il risultato (se presente) può essere memorizzato
con una variante move-result* appropriata come istruzione immediatamente
successiva.
Quando Nei file Dex della versione
Nota: questi opcode sono candidati ragionevoli per il collegamento statico, modificando l'argomento del metodo in modo che sia un offset più diretto (o una coppia di questi). |
73 10x | (non utilizzato) | (non utilizzato) | |
74..78 3rc | invoke-kind/range {vCCCC .. vNNNN}, meth@BBBB 74: invoke-virtual/range 75: invoke-super/range 76: invoke-direct/range 77: invoke-static/range 78: invoke-interface/range |
A: numero di parole dell'argomento (8 bit)B: indice di riferimento al metodo (16 bit)C: registro primo argomento (16 bit)N = A + C - 1 |
Chiama il metodo indicato. Per dettagli, avvertimenti e suggerimenti, consulta la prima invoke-kind
descrizione sopra.
|
79..7a 10x | (non utilizzato) | (non utilizzato) | |
7b..8f 12x | unop vA, vB 7b: neg-int 7c: not-int 7d: neg-long 7e: not-long 7f: neg-float 80: neg-double 81: int-to-long 82: int-to-float 83: int-to-double 84: long-to-int 85: long-to-float 86: long-to-double 87: float-to-int 88: float-to-long 89: float-to-double 8a: double-to-int 8b: double-to-long 8c: double-to-float 8d: int-to-byte 8e: int-to-char 8f: int-to-short |
A: coppia o registro di destinazione (4 bit)B: coppia o registro di origine (4 bit) |
Esegui l'operazione unaria identificata sul registro di origine, memorizzando il risultato nel registro di destinazione. |
90..af 23x | binop vAA, vBB, vCC 90: add-int 91: sub-int 92: mul-int 93: div-int 94: rem-int 95: and-int 96: or-int 97: xor-int 98: shl-int 99: shr-int 9a: ushr-int 9b: add-long 9c: sub-long 9d: mul-long 9e: div-long 9f: rem-long a0: and-long a1: or-long a2: xor-long a3: shl-long a4: shr-long a5: ushr-long a6: add-float a7: sub-float a8: mul-float a9: div-float aa: rem-float ab: add-double ac: sub-double ad: mul-double ae: div-double af: rem-double |
A: coppia o registro di destinazione (8 bit)B: coppia o registro di origine 1 (8 bit)C: coppia o registro di origine 2 (8 bit) |
Esegui l'operazione binaria identificata sui due registri di origine, memorizzando il risultato nel registro di destinazione.
Nota:
a differenza di altre operazioni matematiche |
b0..cf 12x | binop/2addr vA, vB b0: add-int/2addr b1: sub-int/2addr b2: mul-int/2addr b3: div-int/2addr b4: rem-int/2addr b5: and-int/2addr b6: or-int/2addr b7: xor-int/2addr b8: shl-int/2addr b9: shr-int/2addr ba: ushr-int/2addr bb: add-long/2addr bc: sub-long/2addr bd: mul-long/2addr be: div-long/2addr bf: rem-long/2addr c0: and-long/2addr c1: or-long/2addr c2: xor-long/2addr c3: shl-long/2addr c4: shr-long/2addr c5: ushr-long/2addr c6: add-float/2addr c7: sub-float/2addr c8: mul-float/2addr c9: div-float/2addr ca: rem-float/2addr cb: add-double/2addr cc: sub-double/2addr cd: mul-double/2addr ce: div-double/2addr cf: rem-double/2addr |
A: coppia o registro di destinazione e prima origine
(4 bit)B: coppia o registro di seconda origine (4 bit) |
Esegui l'operazione binaria identificata sui due registri di origine, memorizzando il risultato nel primo registro di origine.
Nota:
a differenza di altre operazioni matematiche |
d0..d7 22s | binop/lit16 vA, vB, #+CCCC d0: add-int/lit16 d1: rsub-int (sottrazione inversa) d2: mul-int/lit16 d3: div-int/lit16 d4: rem-int/lit16 d5: and-int/lit16 d6: or-int/lit16 d7: xor-int/lit16 |
A: registro di destinazione (4 bit)B: registro di origine (4 bit)C: costante int firmata (16 bit) |
Esegui l'operazione binaria indicata sul registro indicato (primo
argomento) e sul valore letterale (secondo argomento), memorizzando il risultato nel
registro di destinazione.
Nota:
|
d8..e2 22b | binop/lit8 vAA, vBB, #+CC d8: add-int/lit8 d9: rsub-int/lit8 da: mul-int/lit8 db: div-int/lit8 dc: rem-int/lit8 dd: and-int/lit8 de: or-int/lit8 df: xor-int/lit8 e0: shl-int/lit8 e1: shr-int/lit8 e2: ushr-int/lit8 |
A: registro di destinazione (8 bit)B: registro di origine (8 bit)C: costante int con segno (8 bit) |
Esegui l'operazione binaria indicata sul registro indicato (primo
argomento) e sul valore letterale (secondo argomento), memorizzando il risultato
nel registro di destinazione.
Nota:di seguito sono riportati i dettagli sulla semantica di
|
e3..f9 10x | (non utilizzato) | (non utilizzato) | |
fa 45cc | invoke-polymorphic {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH |
A: numero di parole degli argomenti (4 bit) B: indice di riferimento al metodo (16 bit) C: ricevitore (4 bit) D..G: registri degli argomenti (4 bit ciascuno) H: indice di riferimento al prototipo (16 bit)
|
Richiama il metodo polimorfo della firma indicato. Il risultato (se presente) può essere memorizzato
con una variante move-result* appropriata come istruzione immediatamente
successiva.Il riferimento al metodo deve essere a un metodo polimorfo con firma, ad esempio java.lang.invoke.MethodHandle.invoke o
java.lang.invoke.MethodHandle.invokeExact .Il destinatario deve essere un oggetto che supporta il metodo di firma polimorfa invocato. Il riferimento al prototipo descrive i tipi di argomenti forniti e il tipo di ritorno previsto. Il bytecode invoke-polymorphic potrebbe sollevare eccezioni durante l'esecuzione. Le eccezioni sono descritte nella documentazione dell'API
per il metodo polimorfo della firma invocato.Presente nei file Dex a partire dalla versione 038 .
|
fb 4rcc | invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH |
A: numero di parole degli argomenti (8 bit) B: indice di riferimento al metodo (16 bit) C: ricevitore (16 bit) H: indice di riferimento al prototipo (16 bit) N = A + C - 1
|
Richiama l'handle del metodo indicato. Per informazioni dettagliate, consulta la descrizione di invoke-polymorphic .Presente nei file Dex a partire dalla versione 038 .
|
fc 35c | invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB |
A: numero di parole degli argomenti (4 bit) B: indice di riferimento del sito di chiamata (16 bit) C..G: registri degli argomenti (4 bit ciascuno)
|
Risolve e richiama il sito di chiamata indicato.
Il risultato dell'invocazione (se presente) può essere archiviato con una variante move-result* appropriata come istruzione immediatamente successiva.Questa istruzione viene eseguita in due fasi: risoluzione del sito di chiamata e chiamata del sito di chiamata. La risoluzione del sito di chiamata verifica se il sito di chiamata indicato ha un'istanza java.lang.invoke.CallSite associata.
In caso contrario, il metodo del linker di bootstrap per il sito di chiamata indicato viene invocato utilizzando gli argomenti presenti nel file DEX (vedi call_site_item). Il metodo del linker di bootstrap restituisce un'istanza java.lang.invoke.CallSite che verrà poi associata al sito di chiamata indicato se non esiste alcuna associazione. È possibile che un altro thread abbia già eseguito l'associazione per primo. In questo caso, l'esecuzione dell'istruzione continua con la prima istanza java.lang.invoke.CallSite associata.Viene eseguita l'invocazione del sito di chiamata sul java.lang.invoke.MethodHandle target dell'istanza java.lang.invoke.CallSite risolta. Il target viene invocato come se si eseguisse invoke-polymorphic (descritto sopra) utilizzando l'handle metodo e gli argomenti dell'istruzione invoke-custom come argomenti di un'invocazione dell'handle metodo esatto.Le eccezioni sollevate dal metodo del linker di bootstrap sono racchiuse in un java.lang.BootstrapMethodError . Un BootstrapMethodError viene visualizzato anche se:
038 .
|
fd 3rc | invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB |
A: numero di parole dell'argomento (8 bit) B: indice di riferimento del sito di chiamata (16 bit) C: registro primo argomento (16 bit) N = A + C - 1
|
Risolvi e richiama un sito di chiamata. Per informazioni dettagliate, consulta la descrizione di invoke-custom .Presente nei file Dex a partire dalla versione 038 .
|
fe 21c | const-method-handle vAA, method_handle@BBBB | A: registro di destinazione (8 bit)B: indice dell'handle metodo (16 bit) |
Sposta un riferimento all'handle del metodo specificato dall'indice dato nel
registro specificato. Presente nei file Dex a partire dalla versione 039 .
|
ff 21c | const-method-type vAA, proto@BBBB | A: registro di destinazione (8 bit)B: riferimento al prototipo del metodo (16 bit) |
Sposta un riferimento al prototipo del metodo specificato dall'indice dato nel
registro specificato. Presente nei file Dex a partire dalla versione 039 .
|
Formato del payload del pacchetto di switch
Nome | Formato | Descrizione |
---|---|---|
ident | ushort = 0x0100 | Identificazione di pseudo-opcode |
dimensioni | ushort | numero di voci nella tabella |
first_key | int | primo (e più basso) valore della condizione di switch |
target | int[] | Elenco di size target di ramo relativi. I target sono relativi all'indirizzo dell'opcode di switch, non di questa tabella.
|
Nota: il numero totale di unità di codice per un'istanza di questa tabella è (size * 2) + 4
.
Formato sparse-switch-payload
Nome | Formato | Descrizione |
---|---|---|
ident | ushort = 0x0200 | Identificazione di pseudo-opcode |
dimensioni | ushort | numero di voci nella tabella |
chiavi | int[] | elenco di valori chiave size , ordinati dal più basso al più alto |
target | int[] | elenco di size target di ramo relativi, ciascuno corrispondente al valore della chiave nello stesso indice. I target sono relativi all'indirizzo dell'opcode di switch, non di questa tabella.
|
Nota: il numero totale di unità di codice per un'istanza di questa tabella è (size * 4) + 2
.
formato del payload dei dati dell'array di completamento
Nome | Formato | Descrizione |
---|---|---|
ident | ushort = 0x0300 | Identificazione di pseudo-opcode |
element_width | ushort | numero di byte in ogni elemento |
dimensioni | uint | numero di elementi nella tabella |
di dati | ubyte[] | valori dei dati |
Nota: il numero totale di unità di codice per un'istanza di questa tabella è (size * element_width + 1) / 2 + 4
.
Dettagli dell'operazione matematica
Nota: le operazioni in virgola mobile devono rispettare le regole IEEE 754, utilizzando il metodo di arrotondamento al numero più vicino e il sottoflusso graduale, salvo diversa indicazione.
Opcode | Semantica del linguaggio C | Note |
---|---|---|
neg-int | int32 a; int32 result = -a; |
Complemento a due unario. |
not-int | int32 a; int32 result = ~a; |
Unario a complemento a 1. |
neg-long | int64 a; int64 result = -a; |
Complemento a due unario. |
not-long | int64 a; int64 result = ~a; |
Unario a complemento a 1. |
neg-float | float a; float result = -a; |
Negazione a virgola mobile. |
neg-double | double a; double result = -a; |
Negazione a virgola mobile. |
int-to-long | int32 a; int64 result = (int64) a; |
Firma l'estensione di int32 in int64 . |
int-to-float | int32 a; float result = (float) a; |
Conversione di int32 in float con arrotondamento al numero intero più vicino. In questo modo si perde precisione per alcuni valori.
|
int-to-double | int32 a; double result = (double) a; |
Conversione di int32 in double . |
long-to-int | int64 a; int32 result = (int32) a; |
Troncamento di int64 in int32 . |
long-to-float | int64 a; float result = (float) a; |
Conversione di int64 in float con arrotondamento al numero intero più vicino. In questo modo si perde precisione per alcuni valori.
|
long-to-double | int64 a; double result = (double) a; |
Conversione di int64 in double con arrotondamento al numero intero più vicino. In questo modo si perde precisione per alcuni valori.
|
float-to-int | float a; int32 result = (int32) a; |
Conversione di float in int32 con arrotondamento per difetto. NaN e -0.0 (zero negativo)
vengono convertiti nell'intero 0 . Gli infiniti e i valori con un valore assoluto troppo elevato per essere rappresentato vengono convertiti in 0x7fffffff o -0x80000000 a seconda del segno.
|
float-to-long | float a; int64 result = (int64) a; |
Conversione di float in int64 con arrotondamento per difetto. Qui si applicano le stesse regole per i casi speciali valide per
float-to-int , tranne per il fatto che i valori fuori intervallo
vengono convertiti in 0x7fffffffffffffff o
-0x8000000000000000 a seconda del segno.
|
float-to-double | float a; double result = (double) a; |
Conversione di float in double , mantenendo esattamente il valore.
|
double-to-int | double a; int32 result = (int32) a; |
Conversione di double in int32 con arrotondamento per difetto. Valgono le stesse regole per i casi speciali valide per
float-to-int .
|
double-to-long | double a; int64 result = (int64) a; |
Conversione di double in int64 con arrotondamento per difetto. Valgono le stesse regole per i casi speciali valide per
float-to-long .
|
double-to-float | double a; float result = (float) a; |
Conversione di double in float con arrotondamento al numero intero più vicino. In questo modo si perde precisione per alcuni valori.
|
int-to-byte | int32 a; int32 result = (a << 24) >> 24; |
Troncamento di int32 a int8 , segno
che estende il risultato.
|
int-to-char | int32 a; int32 result = a & 0xffff; |
Troncamento di int32 a uint16 , senza
estensione del segno.
|
int-to-short | int32 a; int32 result = (a << 16) >> 16; |
Troncamento di int32 a int16 , segno
che estende il risultato.
|
add-int | int32 a, b; int32 result = a + b; |
Somma con il complemento a due. |
sub-int | int32 a, b; int32 result = a - b; |
Sottrazione con il complemento a due. |
rsub-int | int32 a, b; int32 result = b - a; |
Sottrazione inversa con il complemento a due. |
mul-int | int32 a, b; int32 result = a * b; |
Moltiplicazione con il complemento a due. |
div-int | int32 a, b; int32 result = a / b; |
Divisione con il complemento a due, arrotondata per difetto (ovvero troncata a numero intero). Viene generato un errore ArithmeticException se
b == 0 .
|
rem-int | int32 a, b; int32 result = a % b; |
Resto del complemento a due dopo la divisione. Il segno del risultato è uguale a quello di a ed è definito con maggiore precisione come result == a - (a / b) * b . Viene generato un ArithmeticException se b == 0 .
|
and-int | int32 a, b; int32 result = a & b; |
E a livello di bit. |
or-int | int32 a, b; int32 result = a | b; |
O a livello di bit. |
xor-int | int32 a, b; int32 result = a ^ b; |
XOR a livello di bit. |
shl-int | int32 a, b; int32 result = a << (b & 0x1f); |
Spostamento a sinistra a livello di bit (con argomento mascherato). |
shr-int | int32 a, b; int32 result = a >> (b & 0x1f); |
Spostamento a destra con segno a livello di bit (con argomento mascherato). |
ushr-int | uint32 a, b; int32 result = a >> (b & 0x1f); |
Spostamento a destra senza segno a livello di bit (con argomento mascherato). |
add-long | int64 a, b; int64 result = a + b; |
Somma con il complemento a due. |
sottolunghezza | int64 a, b; int64 result = a - b; |
Sottrazione con il complemento a due. |
mul-long | int64 a, b; int64 result = a * b; |
Moltiplicazione con il complemento a due. |
div-long | int64 a, b; int64 result = a / b; |
Divisione con il complemento a due, arrotondata per difetto (ovvero troncata a numero intero). Viene generato un errore ArithmeticException se
b == 0 .
|
rem-long | int64 a, b; int64 result = a % b; |
Resto del complemento a due dopo la divisione. Il segno del risultato è uguale a quello di a ed è definito con maggiore precisione come result == a - (a / b) * b . Viene generato un ArithmeticException se b == 0 .
|
and-long | int64 a, b; int64 result = a & b; |
E a livello di bit. |
or-long | int64 a, b; int64 result = a | b; |
O a livello di bit. |
xor-long | int64 a, b; int64 result = a ^ b; |
XOR a livello di bit. |
shl-long | int64 a; int32 b; int64 result = a << (b & 0x3f); |
Spostamento a sinistra a livello di bit (con argomento mascherato). |
shr-long | int64 a; int32 b; int64 result = a >> (b & 0x3f); |
Spostamento a destra con segno a livello di bit (con argomento mascherato). |
ushr-long | uint64 a; int32 b; int64 result = a >> (b & 0x3f); |
Spostamento a destra senza segno a livello di bit (con argomento mascherato). |
add-float | float a, b; float result = a + b; |
Somma con virgola mobile. |
sotto-float | float a, b; float result = a - b; |
Sottrazione con virgola mobile. |
mul-float | float a, b; float result = a * b; |
Moltiplicazione in virgola mobile. |
div-float | float a, b; float result = a / b; |
Divisione con virgola mobile. |
rem-float | float a, b; float result = a % b; |
Resto in virgola mobile dopo la divisione. Questa funzione è diversa
dal resto IEEE 754 ed è definita come
result == a - roundTowardZero(a / b) * b .
|
add-double | double a, b; double result = a + b; |
Somma con virgola mobile. |
doppia mini | double a, b; double result = a - b; |
Sottrazione con virgola mobile. |
mul-double | double a, b; double result = a * b; |
Moltiplicazione in virgola mobile. |
div-double | double a, b; double result = a / b; |
Divisione con virgola mobile. |
rem-double | double a, b; double result = a % b; |
Resto in virgola mobile dopo la divisione. Questa funzione è diversa
dal resto IEEE 754 ed è definita come
result == a - roundTowardZero(a / b) * b .
|