ECL Format: differenze tra le versioni

Da Zulu Hotel Italia - Time Warp.
(istruzione 08 2A/2B: dichiarazione di una variabile (var))
(istruzione 01: accesso a una variabile o costante (load))
Riga 62: Riga 62:
 
* byte 3-4: sempre 00 00
 
* 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)
 
* 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 3B: invocazione di un metodo (method)===
 +
Esegue il metodo W1.const dove const è la costante stringa indicata dal puntatore ai bytes 3-5. Assegna il risultato a W1.
  
 
===istruzione 01: accesso a una variabile o costante (load)===
 
===istruzione 01: accesso a una variabile o costante (load)===

Versione delle 07:41, 24 feb 2015

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, 33 = 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. Nel caso di una variabile, è il suo ID univoco. 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. Se nei registri ci sono più argomenti di quanti necessari, vengono usati i più recenti.

  • 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 3B: invocazione di un metodo (method)

Esegue il metodo W1.const dove const è la costante stringa indicata dal puntatore ai bytes 3-5. Assegna il risultato a W1.

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.
  • 1E: Assegna al registro W1 la priorità dell'oggetto identificata da W1.W2
  • 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 e la carica nel prossimo registro (load)

  • 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 un return generico. Uno di questi è automaticamente incluso alla fine del blocco istruzioni
  • I 5 byte 0F 24 02 00 00 rappresentano end_program

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