Track
/
Lean
Lean
/
Esercizi
/
Assembla
Assembla

Assembla

Difficile

Istruzioni

In questo esercizio definirai la sintassi e il modello di esecuzione di un piccolo linguaggio ispirato al linguaggio assembly x86-64.

L'obiettivo è formalizzare come il codice viene scritto, analizzato ed eseguito in un ambiente limitato.

Modello di esecuzione

Il tuo codice assembly sarà scritto all'interno di un costrutto speciale:

let program := assemble!(
    -- assembly code here
)

Questo costrutto deve produrre un programma, che simula una funzione che esegue il codice assembly e restituisce un valore. Questo programma viene poi chiamato usando la seguente sintassi, dove a, b, c, ecc. sono argomenti:

let result := program(a, b, c, ...)

Tutti gli argomenti e il valore restituito sono interi con segno a 64 bit. È consentito un massimo di 6 argomenti.

Registri

Il valore restituito e tutti gli argomenti vengono passati nei registri. Il tuo linguaggio deve supportare i seguenti registri:

registro ruolo
rdi 1º argomento
rsi 2º argomento
rdx 3º argomento
rcx 4º argomento
r8 5º argomento
r9 6º argomento
rax valore restituito

I registri partono con un valore predefinito di 0, a meno che non vengano usati per passare argomenti alla funzione.

Ad esempio, nel seguente programma, tutti i registri hanno un valore di 0, fatta eccezione per rdi, inizializzato con 10, e rsi, inizializzato con -20:

program(10, -20)

Il valore restituito dal programma è sempre memorizzato in rax.

Note

I nomi dei registri non distinguono maiuscole e minuscole. Ciò significa che rax, RAX e rAx si riferiscono tutti allo stesso registro.

Codice assembly

Ogni riga nel codice assembly può avere due forme:

  • Le etichette contrassegnano punti specifici del programma da usare in alcune istruzioni.
  • Le istruzioni rappresentano operazioni eseguite dal programma.

Se non viene modificato da qualche istruzione, il flusso di esecuzione del programma procede in modo lineare. Ciò significa che una riga precedente viene eseguita completamente prima che venga eseguita la riga successiva.

Etichette

Le etichette hanno la seguente sintassi:

<label>:

Non alterano il valore di alcun registro e non hanno alcun effetto sul programma se non quello di contrassegnare punti specifici del codice, così che possano essere usati dalle istruzioni.

Note

Le etichette distinguono maiuscole e minuscole. Ciò significa che Start, start e sTart sono tutte etichette diverse.

Istruzioni a due operandi

La maggior parte delle istruzioni ha la seguente sintassi:

<opcode> <destination>, <source>

L'opcode indica l'operazione eseguita, usando i valori degli operandi destination e source. Il risultato dell'operazione viene memorizzato nell'operando destination.

Ad esempio, l'istruzione add somma i valori negli operandi destination e source e memorizza questo risultato nell'operando destination.

L'operando destination è sempre un registro, mentre l'operando source può essere un registro o un numero letterale.

Questa è una lista di istruzioni che il tuo programma deve supportare:

opcode operazione eseguita
mov destination := source
add destination := destination + source
sub destination := destination - source
mul destination := destination * source
div destination := destination / source
xor destination := destination ^^^ source
and destination := destination &&& source
or destination := destination ||| source
shl destination := destination <<< source
shr destination := destination >>> source

Oltre a queste, il tuo programma deve supportare l'istruzione cmp a due operandi.

Questa istruzione non modifica alcun registro, ma confronta gli operandi destination e source e imposta uno stato interno del programma su una delle tre opzioni:

  • maggiore di, se destination > source
  • uguale, se destination == source
  • minore di, se destination < source

Come tenere traccia internamente di questo stato dipende da te.

Istruzioni a un operando

Ci sono alcune istruzioni che alterano il flusso del programma, trasferendo l'esecuzione in un altro punto del codice. Si chiamano istruzioni di salto.

Prendono tutte un solo operando, che è un'etichetta che indica la destinazione del salto, cioè il punto del codice in cui l'esecuzione proseguirà:

<opcode> <label>

L'istruzione jmp esegue sempre il salto verso l'etichetta di destinazione.

Le altre istruzioni di salto effettuano il salto solo se lo stato interno del programma è impostato su un valore specifico. Ciò significa che di solito sono precedute da un'istruzione cmp.

Queste sono le istruzioni di salto che il tuo programma deve supportare:

istruzione operazione eseguita
jmp salto incondizionato. Il salto viene sempre eseguito
je salta se lo stato interno è uguale
jl salta se lo stato interno è minore di
jg salta se lo stato interno è maggiore di
Note

Gli opcode delle istruzioni, siano esse a due operandi o a un operando, non distinguono maiuscole e minuscole. Ciò significa che add, ADD e aDd si riferiscono tutte alla stessa istruzione.

Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Lean Exercism

Vuoi iniziare Assembla?

Iscriviti a Exercism per imparare e padroneggiare Lean con 100 esercizi e il mentoring di persone reali, tutto gratis.