Come posso accedere alla sezione dei dati allegata nel linguaggio di script personalizzato?

0

Scusa se il titolo non è chiaro, i suggerimenti su un titolo migliore sono i benvenuti.

Allo scopo di [auto-] istruzione sto scrivendo un linguaggio di scripting giocattolo che dovrebbe essere compilato in bytecode ed essere eseguito su una VM giocattolo.

Questo non sarà un linguaggio completo di turing e conterrà solo strutture di controllo del flusso semplici come if...then...else e nel complesso sarà solo una sequenza di istruzioni diritta.

Ho già praticamente tutto funzionante tranne una parte: vorrei che il mio bytecode avesse una sezione di dati di sola lettura (molto simile a .rodata nei binari nativi). Tuttavia sono bloccato su come faccio riferimento a questo in opcode? Posso dare l'indirizzo dell'inizio del blocco di dati, ma come posso fornire la lunghezza dei dati?

Ad esempio: posso avere un opcode 0x01 per confrontare un valore immediato 0x0005 con i dati nella sezione dati ad un indirizzo 0xf002 (ignora endianness per ora):

0000 0100050002
...
f002 0005000000

Una possibile soluzione che potrei pensare è di anteporre il valore alla lunghezza del blocco di dati (come 0005000000 diventa 0200050000 ) ma ciò porta al problema di essere limitati nella dimensione del blocco dati (cioè se si usa 1 byte come in questo esempio, ovviamente sarà limitato da 255 byte, che alcuni potrebbero dire è sufficiente per tutti) o se fornisci una dimensione sufficientemente grande (ad esempio 8 byte), la dimensione della dimensione sarà molto più grande dei dati effettivi in alcuni casi, che non è desiderabile.

Quale sarebbe un approccio migliore?

    
posta Alexey Kamenskiy 22.01.2018 - 16:31
fonte

1 risposta

3

I normali byte non portano alcun tipo. Invece, le operazioni su questi byte impongono un'interpretazione di questi dati. La maggior parte dei set di istruzioni ha istruzioni diverse per eseguire la stessa operazione ma con tipi di dimensioni diverse. In alternativa, queste istruzioni caricano sempre una "parola" e richiedono al programma di mascherare eventuali bit indesiderati.

Ad esempio, potresti avere questo pseudo-assemblaggio:

LOAD WORD [0xf002]
...
LOAD BYTE [0xf002]
...
; at address 0xf002:
ca ff ee 01 23 ...

Quindi, assumendo parole a 32 bit, la prima istruzione LOAD caricherà ca ff ee 01 , mentre il secondo LOAD otterrebbe solo ca (ignorando l'endianess). Queste due istruzioni di caricamento di solito sono codificate con un codice operativo diverso.

I set di istruzioni per l'hardware in genere non hanno istruzioni che possono elaborare dati di dimensioni variabili. Ma questa restrizione non esiste necessariamente nelle VM. In particolare, una macchina virtuale potrebbe offrire istruzioni per operazioni che verrebbero eseguite come syscalls o chiamate di libreria su hardware reale. L'approccio più flessibile per trattare dati di dimensioni variabili è fornire i dati e le dimensioni di questi dati separatamente . Cioè il set di istruzioni non ha bisogno di avere un concetto di "tipo stringa".

Le dimensioni sarebbero fornite alle istruzioni di elaborazione delle stringhe come argomento separato. Come farlo dipende dalle convenzioni di chiamata. Ad esempio, in una VM basata su stack

; print 3 bytes from string at address 0xf002
CONST 0xf002
CONST 3
PRINT

È quindi responsabilità del programma che genera questi codici opzionali conoscere la lunghezza corretta. Questo è possibile perché il compilatore genera sia le istruzioni che i dati. Invece di posizionare la lunghezza come valore immediato, potrebbe anche essere caricata dai dati. Per esempio:.

CONST 0xf003      ; string start
LOAD BYTE 0xf002  ; load string length
PRINT

Se la stringa è più grande, allora questo è noto staticamente, ad esempio:

CONST 0xf006
LOAD WORD 0xf002
PRINT

Questo accesso alla memoria non elaborata è molto fastidioso e non necessario per una VM. Soprattutto per le VM giocattolo, operare su un modello di oggetti è molto più conveniente.

Un esempio notevole di una VM reale con questo approccio è la JVM. I file .class sono un formato binario ma strutturato che descrive una classe (campi e metodi). Al momento del caricamento, una struttura dati di classe viene generata nella VM. Questa struttura dati contiene una tabella di pool costante da cui il codice può caricare valori per indice.

Molti layout di dati e problemi di caricamento non devono essere risolti all'interno del set di istruzioni. Invece, l'assemblatore e il caricatore possono essere estesi per assicurarsi che offset e dimensioni siano corretti.

    
risposta data 22.01.2018 - 17:34
fonte

Leggi altre domande sui tag