2. La macchina virtuale Java


2.10 Indice delle istruzioni macchina Java

Di seguito è riportato l'elenco delle istruzioni macchina Java. Le istruzioni sono divise in vari gruppi a seconda della loro funzionalità.

  1. Istruzioni che caricano costanti nello stack

    bipush

    iconst_m1
    sipush
    iconst_<n>
    ldc1
    lconst_<l>
    ldc2
    fconst_<f>
    ldc2w
    dconst_<d>
    aconst_null

  2. Istruzioni che caricano variabili locali nello stack

    iload

    fload_<n>
    iload_<n>
    dload
    lload
    dload_<n>
    lload_<n>
    aload
    fload
    aload_<n>

  3. Istruzioni che immagazzinano valori dello stack nelle variabili locali

    store

    dstore
    istore_<n>
    dstore_<n>
    lstore
    astore
    lstore_<n>
    astore_<n>
    fstore
    iinc
    fstore_<n>

  4. Istruzioni per la creazione e la modificazione di array

    newarray

    caload
    anewarray
    saload
    multianewarray
    iastore
    arraylength
    lastore
    iaload
    fastore
    laload
    dastore
    faload
    aastore
    daload
    bastore
    aaload
    castore
    baload
    sastore

  5. Istruzioni che operano sullo stack

    nop

    dup_x1
    pop
    dup2_x1
    pop2
    dup_x2
    dup
    dup2_x2
    dup2
    swap

  6. Istruzioni aritmetiche

    iadd

    idiv
    ladd
    ldiv
    fadd
    fdiv
    dadd
    ddiv
    isub
    imod
    lsub
    lmod
    fsub
    fmod
    dsub
    dmod
    imul
    ineg
    lmul
    lneg
    fmul
    fneg
    dmul
    dneg

  7. Istruzioni logiche

    ishl

    iand
    ishr
    land
    iushr
    ior
    lshl
    lor
    lshr
    ixor
    lushr
    lxor

  8. Istruzioni di conversione dei tipi

    i2l

    f2d
    i2f
    d2i
    i2d
    d2l
    l2i
    d2f
    l2f
    int2byte
    l2d
    int2char
    f2i
    int2short
    f2l

  9. Istruzioni per il controllo di flusso (salto condizionato e incondizionato, etc.)

    ifeq

    if_icmpge
    iflt
    lcmp
    ifle
    fcmpl
    ifne
    fcmpg
    ifgt
    dcmpl
    ifge
    dcmpg
    if_icmpeq
    if_acmpeq
    if_icmpne
    if_acmpne
    if_icmplt
    goto
    if_icmpgt
    jsr
    if_icmple
    ret

  10. Istruzioni di return

    ireturn

    dreturn
    lreturn
    areturn
    freturn
    return

  11. Istruzioni di jump con accesso alle tavole di indirizzamento

    tableswitch

    lookupswitch

  12. Istruzioni per la creazione e la modificazione di campi per gli oggetti

    putfield

    putstatic
    getfield
    getstatic

  13. Istruzioni per la chiamata dei metodi delle classi

    invokevirtual

    invokestatic
    invokenonvirtual
    invokeinterface

  14. Istruzioni per la gestione degli Exception (errori che si verificano durante l'esecuzione)

    athrow

  15. Istruzioni varie per gli oggetti

    new

    instanceof
    newfromname
    verifystack
    checkcast

  16. Istruzioni per il controllo in fase di esecuzione (monitor)

    monitorenter

    monitorexit

  17. Istruzioni per il debugging

    breakpoint

  18. Istruzioni veloci

    • Caricamento veloce di costanti nello stack:

      ldc1_quick

      ldc2w_quick
      ldc2_quick

    • Gestione rapida degli array:

      anewarray_quick

    • Gestione rapida dei campi degli oggetti:

      putfield_quick

      putstatic_quick
      putfield2_quick
      putstatic2_quick
      getfield_quick
      getstatic_quick
      getfield2_quick
      getstatic2_quick

    • Chiamata rapida ai metodi delle classi:

      invokevirtual_quick

      invokestatic_quick
      invokevirtualobject_quick
      invokeinterface_quick
      invokenonvirtual_quick

    • Altre istruzioni veloci varie:

      new_quick

      instanceof_quick
      checkcast_quick

A titolo di esempio, di seguito viene riportata la descrizione particolareggiata delle istruzioni appartenenti al primo gruppo (istruzioni che caricano costanti nello stack). Ogni istruzione è mostrata nella seguente maniera:

<Nome dell'istruzione e relativo codice numerico>

<breve descrizione dell'istruzione>

Sintassi:

<Nome istruzione> <operando 1 (sempre 1 byte)> <operando 2 (sempre 1 byte)>

Stack:

<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