Formato bytecode Dalvik

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.
  • 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'intervallo v0v65535 . 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'istruzione nop 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'intervallo v0v255 .
      • " vBBBB " è il registro sorgente, che deve essere compreso nell'intervallo v0v65535 .
  • 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 packed-switch-payload ", "formato sparse-switch-payload " e "formato fill-array-data-payload " di seguito.

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 v N a v N-1 o v N+1 , quindi le implementazioni devono fare in modo che entrambe le metà di una coppia di registri vengano lette prima che venga scritto qualsiasi cosa.

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 move-wide , sopra.

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 move-wide , sopra.

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, finally ) di pulizia del monitor come pulizia del monitor per quel blocco stesso, come un modo per gestire le eccezioni arbitrarie che potrebbero essere generate a causa dell'implementazione storica di Thread.stop() , pur riuscendo comunque ad avere un'adeguata igiene del monitor.

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é A deve sempre essere un riferimento (e non un valore primitivo), ciò fallirà necessariamente in fase di esecuzione (ovvero genererà un'eccezione) se B fa riferimento a un tipo primitivo.

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é B deve sempre essere un riferimento (e non un valore primitivo), ciò risulterà sempre nella memorizzazione di 0 se C fa riferimento a un tipo primitivo.

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 taglie
C: 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 0 . (Uno spin loop può essere legalmente costruito con goto/32 o includendo un nop come bersaglio prima del ramo.)

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 0 . (Uno spin loop può essere legalmente costruito con goto/32 o includendo un nop come bersaglio prima del ramo.)

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 testare
B: 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 testare
B: 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 sorgente
C: 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 x < y è consigliabile utilizzare cmpg-float ; un risultato pari a -1 indica che il test era vero e gli altri valori indicano che era falso a causa di un confronto valido o perché uno dei valori era NaN .

32..37 22t if- test vA, vB, +CCCC
32: se-eq
33: se-ne
34: se-lt
35: se-ge
36: se-gt
37: se-le
A: primo registro da testare (4 bit)
B: secondo registro da testare (4 bit)
C: offset 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 0 . (Uno spin loop può essere costruito legalmente ramificandosi attorno a un goto all'indietro o includendo un nop come bersaglio prima del ramo.)

38..3d 21t if- test z vAA, +BBBB
38: se-eqz
39: se-nez
3a: if-ltz
3b: se-gez
3c: se-gtz
3d: se-lez
A: registrati per testare (8 bit)
B: offset 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 0 . (Uno spin loop può essere costruito legalmente ramificandosi attorno a un goto all'indietro o includendo un nop come bersaglio prima del ramo.)

3e..43 10x (non utilizzato) (non utilizzato)
44..51 23x arrayop vAA, vBB, vCC
44: 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.

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

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

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

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

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

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

Nota: questi codici operativi sono candidati ragionevoli per il collegamento statico, alterando l'argomento del metodo in modo che sia un offset più diretto (o una coppia di 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 -long (che accettano coppie di registri sia per la prima che per la seconda sorgente), shl-long , shr-long e ushr-long prendono una coppia di registri per la prima sorgente (il valore da spostare ), ma un unico registro per la loro seconda fonte (la distanza di spostamento).

b0..cf 12x binop /2addr vA, vB
b0: add-int/2addr
b1: sub-int/2addr
b2: mul-int/2addr
b3: div-int/2addr
b4: rem-int/2addr
b5: and-int/2addr
b6: or-int/2addr
b7: xor-int/2addr
b8: shl-int/2addr
b9: shr-int/2addr
ba: ushr-int/2addr
bb: add-long/2addr
bc: sub-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 -long/2addr (che accettano coppie di registri sia per la destinazione/prima origine che per la seconda origine), shl-long/2addr , shr-long/2addr e ushr-long/2addr accettano un registro coppia per la destinazione/prima sorgente (il valore da spostare), ma un unico registro per la seconda sorgente (la distanza di spostamento).

d0..d7 22s binop /lit16 vA, vB, #+CCCC
d0: add-int/lit16
d1: rsub-int (sottrazione inversa)
d2: mul-int/lit16
d3: div-int/lit16
d4: rem-int/lit16
d5: 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: rsub-int non ha un suffisso poiché questa versione è il codice operativo principale della sua famiglia. Inoltre, vedere sotto per i dettagli sulla sua semantica.

d8..e2 22b binop /lit8 vAA, vBB, #+CC
d8: add-int/lit8
d9: rsub-int/lit8
da: mul-int/lit8
db: div-int/lit8
dc: rem-int/lit8
dd: 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 rsub-int .

e3..f9 10x (non utilizzato) (non utilizzato)
fa 45cc invoca-polimorfico {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH A: conteggio parole argomento (4 bit)
B: indice di riferimento del metodo (16 bit)
C: ricevitore (4 bit)
D..G: registri 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:
  • il metodo del linker bootstrap non riesce a restituire un'istanza java.lang.invoke.CallSite .
  • il java.lang.invoke.CallSite restituito ha una destinazione di handle del metodo null .
  • la destinazione dell'handle del metodo non è del tipo richiesto.
Presente nei file Dex dalla versione 038 in poi.
fd 3rc invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB A: conteggio parole argomento (8 bit)
B: indice di riferimento del sito di chiamata (16 bit)
C: registro del primo argomento (16 bit)
N = A + C - 1
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 .