Sei sulla pagina 1di 13

Assemblatore per il linguaggio Hack

Codice sorgente (esempio) Codice macchina


//
// Computes
Computes 1+...+RAM[0]
1+...+RAM[0] 0000000000010000
0000000000010000
//
// and stores
and stores the
the sum
sum in
in RAM[1]
RAM[1] 1110111111001000
1110111111001000
@i
@i 0000000000010001
0000000000010001
M=1
M=1 //
// ii == 11 1110101010001000
1110101010001000
0000000000010000
0000000000010000
@sum
@sum 1111110000010000
M=0
M=0 //
// sum
sum == 00
assembler 1111110000010000
0000000000000000
(LOOP) 0000000000000000
(LOOP) 1111010011010000
1111010011010000
@i
@i //
// if
if i>RAM[0]
i>RAM[0] goto
goto WRITE
WRITE 0000000000010010
D=M 0000000000010010
D=M 1110001100000001
1110001100000001
@R0
@R0 0000000000010000
D=D-M 0000000000010000
D=D-M 1111110000010000
1111110000010000
@WRITE
@WRITE 0000000000010001
D;JGT 0000000000010001
D;JGT ...
...
...
... //
// Etc.
Etc.

Prof. Ivan Lanese

Architettura degli Elaboratori Assembler


Assembler

 L’assembler si occupa della traduzione del linguaggio assembly


(human readable) al relativo codice in linguaggio macchina
(machine executable)
 Nel caso del linguaggio Hack, ogni istruzione in linguaggio
assembly viene tradotta in un codice a 16 bit, ad esclusione delle
direttive di dichiarazione di “labels” che semplicemente
definiscono dei simboli
 In input all’assemblatore forniamo un file in linguaggio assembly
Hack (estensione .asm), in output l’assemblatore genera un file
contenente per ogni riga un numero binario a 16 bit scritto in
ASCII (estensione .hack)
 In un sistema reale non scriverebbe in ASCII ma in binario
 I file con estensione .hack possono essere caricati in
CPUEmulator per essere eseguiti

Architettura degli Elaboratori Assembler


Programma assembly
//
// Computes
Computes 1+...+RAM[0]
1+...+RAM[0] Programma assembly =
//
// and stores the
and
@i
stores the sum
sum in
in RAM[1].
RAM[1]. file con un sequenza di linee di
@i
M=1
M=1 // // ii == 11 testo; le linee rilevanti contengono
@sum
@sum una fra le seguenti cose:
M=0
M=0 // // sum
sum == 00
(LOOP)
(LOOP)
@i //
A-instruction
@i // if
if i>RAM[0]
i>RAM[0] goto
goto WRITE
WRITE
D=M
D=M
@0
@0 C-instruction
D=D-M
D=D-M
@WRITE
@WRITE
D;JGT dichiarazione etichette
D;JGT
@i //
// sum
sum +=
+= ii
Possono poi essere presenti
@i
D=M
D=M
@sum
@sum
M=D+M
M=D+M
commenti, spazi bianchi, simboli di
@i
@i
M=M+1
//
// i++
i++ tabulazione ‘\t’, o simboli di fine
linea come ‘\r’ o ‘\n’ :
M=M+1
@LOOP
@LOOP //
// goto
goto LOOP
LOOP
0;JMP
0;JMP
(WRITE)
(WRITE)
@sum
 Commenti iniziano con: //
@sum
D=M
D=M
@1
@1
M=D
(END)
M=D //
// RAM[1]
RAM[1] == the
the sum
sum Sfida: Tradurre tali file in sequenze
(END)
@END
@END di istruzioni a 16 bit eseguibili dal
0;JMP
0;JMP
nostro calcolatore Hack
Architettura degli Elaboratori Assembler
Traduzione di A-instructions

Traduzione in codice macchina:

 Se value è un numero decimale non-negativo, basta considerare


per la sua sequenza “v v … v” la rappresentazione di value in
notazione posizionale binaria tramite 15 bit

 Se value è un simbolo, vedremo dopo come procedere

Architettura degli Elaboratori Assembler


Traduzione di C-instructions

Architettura degli Elaboratori Assembler


Gestione dei simboli

 I simboli sono costiutiti dai seguenti possibili caratteri:


 Lettere minuscole (comprese fra ‘a’ e ‘z’)
 Lettere maiuscole (comprese fra ‘A’ e ‘Z’)
 Cifre decimali (comprese fra ‘0’ e ‘9’)
 Simboli particolari: ‘_’, ‘.’, ‘$’
 Il primo carattere non può essere una cifra decimale
 I simboli sono usati per identificare indirizzi di istruzioni in ROM
(destinazione dei jump) oppure indirizzi in memoria RAM (variabili)
 Alcuni simboli sono già automaticamente prestabiliti:
R0
R0 00 SP
SP 00
R1
R1 11 LCL 11
LCL
R2
R2 22 ARG 22
ARG
...
... THIS
THIS 33
R15
R15 15
15 THAT
THAT 44
SCREEN
SCREEN 16384
16384
KBD
KBD 24576
24576
Architettura degli Elaboratori Assembler
Simboli definiti dal programmatore
@R0
@R0
Etichette: D=M
D=M
Usate per identificare i punti di destinazione @END
@END
D;JLE
delle istruzioni di salto (vedi LOOP e END D;JLE
@counter
@counter
nell’esempio). Definite tramite la direttiva M=D
M=D
@SCREEN
(YYY) che definisce l’etichetta YYY a cui verrà @SCREEN
D=A
D=A
assegnato come valore l’indirizzo di memoria @x
@x
M=D
ROM in cui verrà caricata la prima istruzione M=D
(LOOP)
(LOOP)
successiva alla direttiva (YYY) @x
@x
A=M
A=M
Variabili: M=-1
M=-1
@x
Usate nelle A-instruction per identificare celle @x
D=M
D=M
di memoria RAM da dedicare a specifiche @32
@32
variabili (vedi “counter” e “x” nell’esempio). D=D+A
D=D+A
@x
@x
Riceveranno un valore che va da 16 in poi. I M=D
M=D
valori vengono assegnati seguendo l’ordine in @counter
@counter
MD=M-1
cui tali variabili appaiono (nell’esempio MD=M-1
@LOOP
@LOOP
“counter” varrà 16, mentre “x” varrà 17) D;JGT
D;JGT
(END)
(END)
@END
@END
0;JMP
0;JMP
Architettura degli Elaboratori Assembler
Simboli predefiniti
@R0
@R0
Registri virtuali: D=M
D=M
I simboli R0,…, R15 sono automaticamente @END
@END
D;JLE
predefiniti per far riferimento agli indirizzi di D;JLE
@counter
@counter
memoria RAM 0,…,15 M=D
M=D
@SCREEN
@SCREEN
Puntatori per I/O: D=A
D=A
@x
@x
I simboli SCREEN and KBD fanno riferimento agli M=D
M=D
indirizzi RAM 16384 e 24576, rispettivamente (LOOP)
(LOOP)
@x
(indirizzi base della mappa in memoria dello @x
A=M
A=M
schermo, e della tastiera) M=-1
M=-1
@x
@x
Puntatori di controllo della Virtual Machine: D=M
D=M
@32
I simboli SP, LCL, ARG, THIS, and THAT (assenti @32
D=D+A
D=D+A
nell’esempio a fianco) sono automaticamente @x
@x
M=D
predefiniti per far riferimento agli indirizzi di M=D
@counter
@counter
RAM 0, 1, 2, 3, e 4, rispettivamente MD=M-1
MD=M-1
@LOOP
@LOOP
(I puntatori di controllo della VM saranno discussi D;JGT
D;JGT
(END)
più avanti quando parleremo di Virtual Machine) (END)
@END
@END
0;JMP
0;JMP
Architettura degli Elaboratori Assembler
Gestione dei simboli tramite “symbol table”
Codice sorgente (esempio) Symbol table
R0
R0 00
//
// Computes
Computes 1+...+RAM[0]
1+...+RAM[0]
// R1
R1 11
// and stores
and stores the
the sum
sum in
in RAM[1]
RAM[1] R2 22
@i
@i R2
M=1 ... ...
M=1 // // ii == 11 ... ...
@sum R15
R15 15
15
@sum
M=0 SCREEN 16384
M=0 // // sum
sum == 00 SCREEN 16384
(LOOP) KBD
KBD 24576
24576
(LOOP)
@i
@i //
// if
if i>RAM[0]
i>RAM[0] goto
goto WRITE
WRITE SP
SP 00
D=M
D=M LCL
LCL 11
@R0
@R0 ARG 22
ARG
D=D-M
D=D-M THIS 33
THIS
@WRITE
@WRITE THAT 44
THAT
D;JGT
D;JGT LOOP 44
@i // LOOP
@i // sum
sum +=+= ii WRITE
WRITE 18
18
D=M
D=M END 22
@sum END 22
@sum ii 16
M=D+M 16
M=D+M sum 17
@i // sum 17
@i // i++
i++
M=M+1
M=M+1
@LOOP
@LOOP //
// goto
goto LOOP
LOOP
0;JMP
0;JMP
(WRITE)
(WRITE)
@sum La symbol table viene generata
@sum
D=M
D=M dall’assemblatore e viene usata per
@R1
@R1
M=D
M=D //
// RAM[1]
RAM[1] == thethe sum
sum
tradurre i simboli nei relativi valori
(END)
(END)
@END
@END
0;JMP
0;JMP

Architettura degli Elaboratori Assembler


Gestione dei simboli tramite “symbol table”
Codice sorgente (esempio) Symbol table
R0
R0 00
//
// Computes
Computes 1+...+RAM[0]
1+...+RAM[0]
// R1
R1 11
// and stores
and stores the
the sum
sum in
in RAM[1]
RAM[1] R2 22
@i
@i R2
M=1 ... ...
M=1 // // ii == 11 ... ...
@sum R15
R15 15
15
@sum
M=0 SCREEN 16384
M=0 // // sum
sum == 00 SCREEN 16384
(LOOP) KBD
KBD 24576
24576
(LOOP)
@i
@i //
// if
if i>RAM[0]
i>RAM[0] goto
goto WRITE
WRITE SP
SP 00
D=M
D=M LCL
LCL 11
@R0
@R0 ARG 22
ARG
D=D-M
D=D-M THIS 33
THIS
@WRITE
@WRITE THAT 44
THAT
D;JGT
D;JGT LOOP 44
@i // LOOP
@i // sum
sum +=+= ii WRITE
WRITE 18
18
D=M
D=M END 22
@sum END 22
@sum ii 16
M=D+M 16
M=D+M sum 17
@i // sum 17
// i++
@i
M=M+1
M=M+1
i++
Gestione della symbol table:
@LOOP
@LOOP //
0;JMP
// goto
goto LOOP
LOOP - iniziale inserimento dei simboli predefiniti
0;JMP
(WRITE)
(WRITE)
- prima passata del file in input: inserimento
@sum
@sum
D=M
delle etichette dichiarate tramite direttiva
D=M
@R1
@R1
(YYY) con relativo valore
(END)
M=D
M=D //
// RAM[1]
RAM[1] == thethe sum
sum - seconda passata del file in input:
(END)
@END
@END
i simboli in A-instruction non ancora in symbol
0;JMP
0;JMP table vengono aggiunti con relativi valori
Architettura degli Elaboratori Assembler
Il processo di assemblaggio

 Inizializzazione:
 Apertura in lettura del file in input
 Inizializzazione della symbol table con i simboli predefiniti
 Prima passata:
 Si scorre l’input per inserire le etichette in symbol table: per
sapere che valore assegnare alle etichette si contano le A- e le C-
instructions (iniziando da 0) e quando si incontra una etichetta le
si assegna il valore di tale contatore in quel momento
 Seconda passata:
 Si apre in scrittura il file di output e si scorre di nuovo l’input:
 per A- e C-instruction si scrive in output il relativo codice
 Per i simboli in A-instruction: si cerca il valore in symbol
table; se il simbolo è assente si assegna un valore
(partendo da 16) e si memorizza il valore in symbol table

Architettura degli Elaboratori Assembler


Il risultato
Codice sorgente (esempio) Codice macchina
//
// Computes
Computes 1+...+RAM[0]
1+...+RAM[0] 0000000000010000
0000000000010000
//
// and stores
and stores the
the sum
sum in
in RAM[1]
RAM[1] 1110111111001000
1110111111001000
@i
@i 0000000000010001
0000000000010001
M=1
M=1 // // ii == 11 1110101010001000
1110101010001000
@sum
@sum 0000000000010000
0000000000010000
M=0
M=0 // // sum
sum == 00 1111110000010000
1111110000010000
(LOOP)
(LOOP) 0000000000000000
0000000000000000
@i
@i //
// if
if i>RAM[0]
i>RAM[0] goto
goto WRITE
WRITE 1111010011010000
1111010011010000
D=M
D=M 0000000000010010
0000000000010010
@R0
@R0 1110001100000001
1110001100000001
D=D-M
D=D-M 0000000000010000
0000000000010000
@WRITE 1111110000010000
@WRITE
D;JGT
D;JGT
assemblaggio 1111110000010000
0000000000010001
0000000000010001
@i
@i //
// sum
sum +=+= ii 1111000010001000
1111000010001000
D=M
D=M 0000000000010000
0000000000010000
@sum
@sum 1111110111001000
1111110111001000
M=D+M
M=D+M 0000000000000100
0000000000000100
@i
@i //
// i++
i++ 1110101010000111
1110101010000111
M=M+1
M=M+1 0000000000010001
0000000000010001
@LOOP
@LOOP //
// goto
goto LOOP
LOOP 1111110000010000
1111110000010000
0;JMP
0;JMP 0000000000000001
0000000000000001
(WRITE)
(WRITE) 1110001100001000
1110001100001000
@sum
@sum 0000000000010110
0000000000010110
D=M
D=M 1110101010000111
1110101010000111
@R1
@R1
M=D
M=D //
// RAM[1]
RAM[1] == thethe sum
sum
(END)
(END)
@END
@END
Nota: solo le linee con A- o C-instructions
0;JMP
0;JMP generano un relativo codice macchina
Architettura degli Elaboratori Assembler
Qualche consiglio

 Procedere per fasi:


 Implementare prima un assemblatore che non considera i simboli
 Non serve quindi la symbol table
 Basta una sola passata
 Deve generare un file con il medesimo nome dell’input con
l’estensione .asm sostituita da .hack
 Controllare la correttezza usando dei programmi in assembly
che non utilizzano simboli
 Passare poi all’implementazione completa:
 Implementare (separatamente) la struttura dati symbol table
 Estendere l’implementazione precedente per fare le due
passate come da slide precedenti
 Controllare correttezza (Pong.asm come esempio non banale)
 Caricate il file Pong.hack generato dal vostro assemblatore in
CPUEmulator e … buon divertimento!
Architettura degli Elaboratori Assembler

Potrebbero piacerti anche