<schema di ciò che avviene nello stack degli operandi>
<eventuale descrizione più dettagliata dell'istruzione>
Gli operandi che seguono l'istruzione sono sempre numeri a 8 bit. Lo schema di ciò che avviene nello
stack degli operandi è del genere che segue:
(...) valore1, valore2 => (...) valore3
Questo schema va interpretato nella seguente maniera: prima dell'esecuzione dell'istruzione, il
valore1 e il valore2 (entrambi lunghi 32 bit) si trovano alla sommità dello stack degli operandi
(l'indice dello stack aumenta da sinistra verso destra). L'esecuzione dell'istruzione preleva valore1 e
valore2 dallo stack (pop) e vi sostituisce (push) il risultato valore3. Il resto dello stack è indicato con
(...) e rimane invariato dopo l'esecuzione dell'istruzione.
Per indicare i dati lunghi 64 bit (interi lunghi e float doppia precisione) che occupano ciascuno due
posizioni dello stack, si usa la seguente notazione:
valore1-word1, valore1-word2
ovvero si mostrano esplicitamente le due posizioni dello stack occupate da un singolo valore (ad
esempio valore1).
Quasi tutte le istruzioni prelevano i loro operandi dallo stack degli operandi e mettono i loro risultati
sempre nello stesso stack. Perciò nella descrizione che segue lo stack degli operandi sarà considerato
per default la sorgente e la destinazione degli operandi e verrà quindi taciuto tutte le volte che una
istruzione fa uso di esso. In altre parole, quando non è riportata la sorgente e la destinazione degli
operandi di una istruzione, essa è da considerarsi lo stack degli operandi. Parimenti, tutte le volte che
la sorgente e la destinazione degli operandi non è lo stack degli operandi, essa verrà esplicitamente
indicata.
Per esempio, nella descizione dell'istruzione iload che prende un intero dalle variabili locali e lo mette
nello stack degli operandi, sarà detto simpliciter "iload carica un intero dalle variabili locali". Si
dovrà sottintendere che la destinazione di iload è lo stack degli operandi.
La maggior parte delle istruzioni non altera il normale flusso computazionale, ovvero fa avanzare il
program counter fino alla istruzione successiva. Perciò verrà fatta menzione dello stato del program
counter solo per le istruzioni che alterano in maniera anomala il flusso computazionale (ovvero
quando il pc non viene fatto avanzare fino alla istruzione successiva).
Istruzioni che caricano costanti nello stack
- bipush = 16
- push di un intero di un byte con segno
sintassi:
- bipush byte1
stack:
- (...) => (...) valore
- sipush = 17
- push di un intero di due byte con segno
sintassi:
- sipush byte1 byte2
stack:
- (...) => (...) valore
- ldc1 = 18
- push di una costante dal costant pool
sintassi:
- ldcl indexbyte1
stack:
- (...) => (...) valore
indexbyte1 è l'indice (8 bit senza segno) della costante in questione nel costant pool della classe
corrente.
- ldc2 = 19
- push di una costante dal costant pool
sintassi:
- ldc2 indexbyte1 indexbyte2
stack:
- (...) => (...) valore
indexbyte1 e indexbyte2 sono usati per costruire un intero 16-bit senza segno per accedere alla
posizione voluta del costant pool della classe corrente.
- ldc2w = 20
- push di un intero lungo o di un float doppia precisione dal costant pool
sintassi:
- ldc2w indexbyte1 indexbyte2
stack:
- (...) => (...) valore-word1, valore-word2
indexbyte1 e indexbyte2 sono usati per costruire un intero 16-bit senza segno per accedere alla
posizione voluta del costant pool della classe corrente.
- aconst_null = 1
- push dell'oggetto null
sintassi:
- aconst_null
stack:
- (...) => (...) null
iconst_m1 = 2
- push del valore costante -1
sintassi:
- iconst_m1
stack:
- (...) => (...) -1
- iconst_<n> = <n> + 3 con <n> = 0, 1, 2, 3, 4, 5
- push dell'intero <n>, con <n> = 0, 1, 2 ,3 ,4 ,5
sintassi:
- iconst_0, oppure iconst_1, oppure iconst_2, oppure iconst_3, oppure iconst_4, oppure iconst_5
stack:
- (...) => (...) <n>
- lconst_<l> = <l> + 9 con l = 0, 1
- push dell'intero lungo <l>, con <l> = 0,1
sintassi:
- lconst_0 oppure lconst_1
stack:
- (...) => (...) <l>-word1, <l>-word2
- fconst_<f> = <f> + 11 con <f> = 0, 1, 2
- push del float singola precisione <f>, con <f> = 0, 1, 2
sintassi:
- fconst_0, oppure fconst_1, oppure f_const_2
stack:
- (...) => (...) <f>
- dconst_<d> = <d> + 14 con <d> = 0, 1
- push del float doppia precisone <d>, con <d> = 0, 1
sintassi:
- dconst_0, oppure dconst_1
stack:
- (...) => (...) <d>-word1, <d>-word2