In che modo esattamente il codice byte è "analizzato"?

2

In che modo Bytecode è "analizzato"?

Ho capito che Bytecode è una rappresentazione binaria e intermedia della sintassi di un determinato linguaggio di programmazione. Alcuni linguaggi di programmazione convertono il loro testo sorgente in Bytecode che viene poi scritto in un file. In che modo le macchine virtuali di quelle lingue "analizzano" il loro Bytecode?

Per limitare questa domanda, prendi il Bytecode di Python per esempio. Quando Python Virtual Machine inizia a leggere il Bytecode da un file *.pyc , in che modo la Virtual Machine traduce il flusso di byte che sta leggendo, in istruzioni specifiche?

Quando la Virtual Machine legge bytecode da un file, sono a conoscenza del fatto che il bytecode è un lungo flusso di byte. In che modo, quindi, il bytecode viene suddiviso in blocchi utili? Come viene trasformato in un codice operativo e gli argomenti opcode?

Ad esempio, supponiamo che la macchina virtuale stia leggendo nel bytecode per aggiungere due numeri. La Virtal Machine vede l'istruzione 0x05 , che significherebbe "aggiungi due numeri".

Ogni numero può essere rappresentato da un diverso numero di byte, quindi come dovrebbe la macchina virtuale sapere quanti byte avrebbe bisogno di leggere in anticipo per raccogliere gli argomenti per l'op 0x05 ?

    
posta Christian Dean 03.11.2016 - 15:40
fonte

3 risposte

9

Penso che la tua confusione derivi dal pensare ai bytecode come a un linguaggio che viene interpretato dalla macchina virtuale. Sebbene questo sia tecnicamente un modo corretto per descriverlo, ti porta ad alcune ipotesi su cose che non sono corrette.

La prima cosa da capire è che bytecode è un tipo di codice macchina . L'unica cosa che lo rende diverso dal codice macchina che la tua CPU capisce è che la macchina in questo caso è virtuale (l'hardware che utilizza direttamente bytecode è possibile). Potrebbe sembrare una grande distinzione, ma se si considera cosa fanno gli emulatori, la macchina di destinazione è virtuale o meno non ha molta importanza nel contesto del linguaggio macchina.

Il codice macchina è facile da analizzare per i computer perché è appositamente progettato per renderlo facile. La distinzione principale tra i linguaggi delle macchine e le lingue più elevate conosciute dalla maggior parte delle persone è che questi ultimi sono generalmente costruiti per essere facili da usare per gli umani.

Questo articolo del 1997 su bytecode java potrebbe aiutare. Esaminiamo un esempio tratto da quel testo:

84 00 01

Per il primo byte (chiamato opcode) è 84. Possiamo cercare che cosa significhi questo opcode e scoprire che è iinc (incrementa la variabile locale #index per byte firmati const) e che i due seguenti byte indicano rispettivamente l'indice della variabile e l'importo. La JVM quindi prende quell'istruzione e la traduce (seguendo le specifiche del linguaggio) in istruzioni macchina che corrispondono alle istruzioni del bytecode.

    
risposta data 03.11.2016 - 17:26
fonte
4

I codici byte sono decodificati. Sono progettati come un set di istruzioni per il processore. Perché i codici byte sono di lunghezza variabile, anche se sappiamo dove sono, per decodificarli, devi decodificare dall'inizio (di solito di un metodo).

Quando raggiungi un'istruzione di branca (soprattutto condizionale) potresti scegliere di seguire l'obiettivo del ramo o il fall thru (istruzione successiva). Se tu fossi un interprete, faresti il primo, e quando JIT, probabilmente faresti il secondo.

Ogni byte codificato dice qualcosa sull'istruzione da eseguire e sulla sua lunghezza. Le operazioni semplici e comuni sono codificate all'interno di un singolo byte. Altre operazioni utilizzano byte aggiuntivi. Il decoder controlla i valori dei byte fino a quel momento e può quindi determinare in minima parte se l'istruzione è completata o richiede un altro byte. Alcune codifiche potrebbero indicare più byte aggiuntivi.

Dai un'occhiata al formato di file di classe bytecode Java e anche all'architettura di set di istruzioni VAX, che è di lunghezza variabile e molto regolare. Il bytecode Java utilizza un'architettura stack ed è di livello abbastanza elevato (dato che è bytecode), mentre VAX è una macchina di registro e di basso livello. (Puoi anche guardare x86, ma è meno regolare e quindi più complicato, IMHO.)

    
risposta data 03.11.2016 - 18:07
fonte
3

Il file avrà un'intestazione piccola con informazioni sulla versione, in cui si trova il bytecode eseguibile (più forse informazioni sulle funzioni in esso contenute) e dove si trovano i dati costanti (come le stringhe). Su stackoverflow è già stata posta la domanda sul bytecode di python.

Il bytecode stesso è molto spesso una sintassi molto semplice. Dove i primi pochi byte indicano quale operazione deve essere eseguita e quali operandi sono necessari. Il bytecode sarà progettato in modo che quando si legge il byte per byte ci sia un'interpretazione univoca delle istruzioni.

Per dare un esempio che rende i byte per operazione molto espliciti, c'è SPIR -V. La prima parola di 4 byte di ogni istruzione è costruita come lunghezza di 2 byte + opcode a 2 byte.

    
risposta data 03.11.2016 - 17:36
fonte

Leggi altre domande sui tag