ECL Format: differenze tra le versioni
(→istruzione 08 25/26: salto condizionale (gotoif)) |
(→istruzione 08 2A/2B: dichiarazione di una variabile (var)) |
||
Riga 76: | Riga 76: | ||
===istruzione 08 2A/2B: dichiarazione di una variabile (var)=== | ===istruzione 08 2A/2B: dichiarazione di una variabile (var)=== | ||
Dichiara una variabile | Dichiara una variabile | ||
− | * byte 2: probabilmente identifica lo scope. 2B = globale, 2A = | + | * byte 2: probabilmente identifica lo scope. 2B = globale, 2A = locale |
* byte 3-5: l'ID univoco della variabile | * byte 3-5: l'ID univoco della variabile | ||
Versione delle 02:42, 24 feb 2015
Indice
- 1 Codifica dei tipi
- 2 Header
- 3 Struttura
- 3.1 Program - codice 04 00
- 3.2 Usages - codice 01 00
- 3.3 Istruzioni - codice 02 00
- 3.3.1 elementi
- 3.3.2 istruzione xx 2F: run
- 3.3.3 istruzione 01: accesso a una variabile o costante (load)
- 3.3.4 istruzione 02: assegnazione (assign)
- 3.3.5 istruzione 03: pulizia dei registri (clear)
- 3.3.6 istruzione 08 2A/2B: dichiarazione di una variabile (var)
- 3.3.7 istruzione 08 25/26: salto (goto)
- 3.3.8 istruzione 0F: return
- 3.4 Costanti - codice 03 00
Codifica dei tipi
All'interno del file, sono condificati dati di più tipi primitivi a cui si farà riferimento successivamente. Le codifiche finora individuate sono:
- stringa a lunghezza fissa: La lunghezza è indicata preventivamente all'interno del blocco che ne fa uso o altrove. È rappresentata da un numero fisso di bytes, dove quelli non utilizzati sono impostati a NULL.
- stringa a lunghezza variabile: Si tratta di un numero variabile di bytes stringa di cui l'ultimo è sempre NULL e rappresenta la fine della stringa stessa
- numero intero: gli interi sono codificati sempre come 4 bytes, ordinati dal meno al più significativo (quindi invertiti, da un punto di vista algebrico). Sono sempre signed: il valore massimo per un intero è 0x7FFFFFFF, rappresentato come FF FF FF 7F. I valori negativi sono rappresentati partendo da FF FF FF FF che significa -1 e poi sottraendo la rappresentazione del valore come se fosse (intero - 1); ad esempio -255 è rappresentato come 01 FF FF FF.
- numeri a virgola mobile (float): i numeri a virgola mobile sono codificati sempre come 8 bytes (da chiarire in che formato, probabilmente 4 bytes base + 4 bytes esponente)
Header
Ogni file inizia con un header di 6 bytes così definito:
- byte 1-2: rappresentano il magic number del formato ("CE")
- byte 3: rappresenta il numero di versione (02 per POL093)
- byte 4: sempre 00
- byte 5: contiene un valore da decodificare (tra 00 e 07)
- byte 6: sempre 00
Struttura
Successivamente all'header, il file ECL sembra avere una struttura a blocchi. Di seguito sono elencati quelli noti, riportati nello stesso ordine in cui compariranno all'interno del file.
Ciascun blocco inizia con 6 (2+4) bytes. Di questi 6 bytes, i primi 2 rappresentano il codice del blocco, mentre i successivi 4 rappresentano, sotto forma di intero, la lunghezza del blocco, in bytes, non conteggiando i 6 bytes dell'intestazione stessa.
Fa eccezione il codice 01 00 per cui la lunghezza viene indicata sempre come 0.
Program - codice 04 00
Questo blocco definisce la direttiva program.
Non è sempre presente: ad esempio, non è usato nello script generale di startup start.ecl.
I primi 6 bytes sono 04 00 - 10 00 00 00, seguono 16 bytes di cui solo il primo sembra essere usato ed indica il numero di argomenti accettati dal blocco program (01, 02, etc...).
Gli altri bytes sono sempre lasciati a NULL.
Usages - codice 01 00
I file .em contenenti le funzioni di sistema importati con la direttiva use sono specificate immediatamente dopo l'header. Ogni blocco use ha una dimensione variabile.
I primi 6 bytes sono 01 00 00 00 00 00, segue un blocco di 13 bytes così suddiviso:
- bytes 1-9: contengono il nome dell'usage sotto forma di stringa a lunghezza fissa
- byte 10: indica il numero di funzioni utilizzate da questo file
- bytes 11-13: sempre NULL
Segue la lista delle funzioni utilizzate da questo file, sotto forma 34 bytes ripetuti per il numero di volte indicato dal byte 10. Di questi 34 bytes, i primi 33 rappresentano una stringa a lunghezza fissa contenente il nome della funzione, mentre l'ultimo byte indica il numero di parametri accettati dalla funzione stessa.
"basic" e "basicio" sembrano essere sempre i primi due usages e sono inclusi implicitamente, e ribaditi quindi nel file ECL, anche se non dichiarati nello script sorgente.
Istruzioni - codice 02 00
ATTENZIONE!!! È probabile che questa sezione contenga ancora molti errori o imprecisioni
Il blocco segue la struttura sopra citata: nell'intestazione è indicata la lunghezza del blocco in byte. Segue un intero che indica nuovamente la lunghezza del blocco meno i 4 byte che compongono l'intero stesso, per un totale di 10 byte di intestazione.
I successivi byte rappresentano le istruzioni stesse e sono sempre un numero di byte divisibile per 5.
Un'istruzione è composta da 5 byte. Se il 2°byte è 2F, questo indica il codice istruzione, altrimenti il 1° byte, indica il codice istruzione.
elementi
All'interno di una istruzione, si possono trovare uno o più dei seguenti elementi che si ripetono, tutti a lunghezza fissa:
- intero3 (3 byte): Si tratta di un intero che ha lo stesso formato dell'intero definito precedentemente, ma manca del byte più significativo, che si assume essere sempre 00.
- puntatore (4 byte):
- byte 1: Il tipo di argomento: 00 = intero, 01 = float, 02 = stringa, aggiungendo 50 (0x32) se si tratta di una variabile
- byte 2-4: Se il byte precedente indica una costante, è l'offset all'interno del blocco delle costanti (intestazione esclusa): indica la posizione in byte dell'argomento da leggere. È da notare che le stringhe possono non essere lette dall'inizio: ad esempio, una stringa "abc" può essere usata come stringa "bc" semplicemente puntando al secondo carattere anziché all'inizio della stringa. Se il byte precedente indica invece una variabile, è l'ID univoco della variabile. Rappresentato come intero3.
istruzione xx 2F: run
Esegue una funzione builtin (use). Si tratta di un'istruzione anomala, in quanto identificata dal secondo byte. Gli argomenti passati sono quelli precedentemente caricati nei registri Wx.
- byte 1: indica il numero progressivo (partendo da 0) della funzione da eseguire, nell'ordine in cui è citata all'interno del blocco usage
- byte 3-4: sempre 00 00
- byte 5: indica a quale blocco usage fa riferimento l'istruzione (00 solitamente è basic, 01 basicio e 02 quello indicato dalla prima direttiva "use" del sorgente)
istruzione 01: accesso a una variabile o costante (load)
Sposta una variabile o costante in un registro temporaneo che chiameremo W1 per essere successivamente utilizzata da una funzione. Se viene chiamata più volte, il registro utilizzato è il successivo (W2, W3, etc...): utile per funzioni che accettano più argomenti. I byte 2-4 rappresentano il puntatore alla variabile o costante.
istruzione 02: assegnazione (assign)
L'istruzione cambia significato in base al valore del byte 2:
- 08/42: Assegna il valore indicato dal registro W2 al registro W1 (W1 := W2). I byte 3-5 sono sempre 00. Sempre che sia usato 08 se l'assegnazione avviene contestualmente alla dichiarazione, altrimenti 42.
- 38: Assegna il nome della variabile al blocco program. I byte 3-5 sono un puntatore alla costante. L'ID della variabile usato è automaticamente il primo libero.
istruzione 03: pulizia dei registri (clear)
Pulisce tutti i registri temporanei Wn. Si presenta sempre nella forma 03 19 00 00 00.
istruzione 08 2A/2B: dichiarazione di una variabile (var)
Dichiara una variabile
- byte 2: probabilmente identifica lo scope. 2B = globale, 2A = locale
- byte 3-5: l'ID univoco della variabile
istruzione 08 25/26: salto (goto)
Salta alla posizione indicata. Se il salto è condizionale, salta solo dopo aver valutato il valore nel registro registro W1
- byte 2: 25 = salta se W1 è TRUE, 26 = salta se W1 è false, 27 = salto incondizionato
- byte 3-5: posizione a cui effettuare il salto
istruzione 0F: return
I 5 byte 0F 20 00 00 00 rappresentano l'istruzione "return". Un return è automaticamente incluso alla fine del blocco istruzioni
Costanti - codice 03 00
In questo blocco, l'ultimo del file, sono contenute le costanti usate all'interno del file stesso.
L'inizio del blocco è indicato dai 6 bytes 03 00 XX XX XX XX: dove XX rappresenta la lunghezza del blocco, in formato intero: sembra sempre uguale all'intero indicato dai successivi 4 bytes + 4.
I successivi 4 bytes rappresentano un intero che indica il numero di bytes da cui è composta la sezione delle costanti + 1 (ovvero indica 1 per 0 bytes, 2 per 1 byte, etc...).
Ad esempio, un blocco costanti contenente 4 bytes di dati puri inizierà con: 03 00 - 09 00 00 00 - 05 00 00 00.
Possono essere presenti i seguenti tipi di dati:
- stringhe a lunghezza variabile
- interi
- float