Laboratorio di Architettura
lezione 2
Massimo Marchiori
W3C/MIT/UNIVE
Linguaggi
l E’
possibile programmare il computer
usando vari linguaggi di programmazione
l Ogni linguaggio ha i suoi pro e contro
Alla fine…
l Pero’,
l’unico linguaggio che il computer
capisce e’ il linguaggio macchina
l à Per usare altri linguaggi, occorre usare
qualcosa in grado di “far capire” al
computer gli altri linguaggi
INTERPRETI
l Un
INTERPRETE per un certo linguaggio
L e’ un programma che “interpreta”
appunto il linguaggio L e fa’ si’ che questo
venga correttamente eseguito dal computer
l Dato un interprete I, e un programma P nel
linguaggio L, indichiamo con I(P)
l’esecuzione di P da parte di I.
VANTAGGI
l L’interprete
puo’ non limitarsi solo a
eseguire il programma, ma puo’ fornire altri
mezzi per controllarne l’esecuzione
l Esempi: esecuzione passo passo, finestre di
controllo delle variabili, trace modes,
breakpoint’s etc etc.
là
DEBUG
(trovare, e togliere, gli errori (“bugs”))
SVANTAGGI
l Essendo
una simulazione, tipicamente
l’interprete “interpreta” il programma ogni
volta che viene eseguito
l à LENTEZZA
l à spesso, per eseguire un programma, ho
bisogno dell’interprete
COMPILATORI
l Il
COMPILATORE, invece, e’ un
programma che prende un programma in un
linguaggio L e lo traduce in un programma
in un altro linguaggio
l Il SOURCE LANGUAGE (“sorgente”)
viene tradotto nel
TARGET LANGUAGE (“obiettivo”)
CASO TIPICO
l Il
caso tipico del compilatore e’ quando il
TARGET LANGUAGE e’ il linguaggio
macchina
VANTAGGI
l Non
ho piu’ bisogno del compilatore, una
volta tradotto il programma
l (nel caso tipico): maggiore velocita’, visto
che il programma risultante e’ in linguaggio
macchina
SVANTAGGI
l Meno
flessibile dell’interprete per il
debugging
l Piu’ difficile da scrivere
SCENARIO
l
l
l
l
l
Nuovo computer, unico linguaggio disponibile:
linguaggio macchina
Volete usare il vostro linguaggio di
programmazione preferito L
Primo passo: scrivete un interprete I per far
correre i programmi in L
VANTAGGI: facile da scrivere, facile fare il
debug dei programmi
SVANTAGGI: lento, lento, lento…, e per far
correre un programma (“hello world”…) occorre
portarvi dietro tutto l’interprete…
SCENARIO (cont.)
là
scrivere un compilatore C per L
Soluzione 1
l Scrivete
il compilatore in linguaggio
macchina
l à molto difficile
Soluzione 2
l Scrivete
il vostro compilatore C nel
linguaggio L (..!!)
l à lo usate con l’interprete I : I(C)
l à gli date in input proprio il compilatore
stesso (C):
I(C)(C)
l à et voila’, avete il vostro compilatore:
I(C)(C)
Cioe’…
l Il
SELF-COMPILING COMPILER…
(il compilatore che compila se stesso…)
l Nota: in letteratura, spesso I(C) si scrive
solo C, per cui il self-compiling compiler
diventa semplicemente C(C)
IMPORTANZA
del self-compiling compiler
l
l
l
l
Anzitutto, come detto, concettuale:
anche qui, l’idea fondamentale, alla base
dell’architettura del computer, che DATO e
PROGRAMMA sono la stessa cosa
E poi, pratica; permette di ottenere un
compilatore:
Come visto nello scenario, quando ho poche
risorse
Quando il linguaggio L e’ molto potente
DATI
lI
dati in un computer sono numeri (numeri
interi):
13124, 51674848, 31643750954-70920
l Ma attenzione, come sono “veramente”
contenuti i dati nel computer?
SISTEMI DI NUMERAZIONE
l Noi
usiamo il “sistema decimale”
l Ma, ci sono ovviamente vari altri modi di
scrivere i numeri:
l Uno, due, tre, quattro, cinque, sei, sette...
l Antichi:
I, II, III, IV, V, VI, VII, VIII, IX, X, …
l E ancora piu’ antichi…(!):
•, • •, • • •, • • • •, • • • • •, • • • • • •, …
Sistemi di Numerazione
l Noi
usiamo un sistema di numerazione
POSIZIONALE a dieci cifre (cosiddetto
DECIMALE, o a BASE DIECI)
DECIMALE
l Dieci
cifre:
“0” à “”
“1” à “•”
“2” à “••”
…
“9” à “•••••••••”
POSIZIONALE
l “452”
significa:
“2” +
“5” * (“9” + “1”)
“4” * (“9” + “1”) * (“9” + “1”)
l Allora, “10” significa “1”*(“9”+”1”)
che e’ proprio uguale a “9”+”1”, e quindi…
l “452” puo’ essere scritto come
“2” + “5” * “10” + “4” * “10” * “10”
DIECI CIFRE?
l Ora,
PERCHE’ PROPRIO DIECI CIFRE??
l …. Quante dita abbiamo? (!)
l Ma, lo stesso trucco si puo’ fare con un
numero qualsiasi di cifre
DUE CIFRE
l
l
l
Due cifre (dette anche bits):
“0” à “”
“1” à “•”
“101” allora significa:
“1” +
“0” * (“1”+”1”) +
“1” * (“1”+”1”) * (“1”+”1”)
Tradotto nel nostro sistema:
1+ 0*2 + 1*2*2 = 5
TANTE CIFRE…
(ad esempio, 36)
l “0”
à “”
…
“9” à “•••••••••”
“A” à “••••••••••”
“B” à “•••••••••••”
…
“Z” à “•••••••••••••••••••••••••••••••••••”
36 cifre…
l Cosi’
ad esempio,
“1H2” significa
“1” +
“H” * (“Z” + “1”) +
“1” * (“Z” + “1”) + (“Z” + “1”)
l Che nel nostro sistema sarebbe:
1+ 7*36 + 1*36*36
Come si distingue?
l “101”:
in quale sistema di numerazione?
l 1012 indica 101 nel sistema binario
l 10110 indica 101 nel sistema decimale
l 101n indica 101 nel sistema a n cifre
l Talvolta, si usa anche 101bin , 101dec, e
101hex (o anche 0x101), per indicare i
sistemi in base 2, 10 e 16 rispettivamente
E il Computer…?
l Quante
cifre usa il computer?
l DUE! (sistema binario)
l à Chiedete a Salvatore Orlando il
perche’…
Pero’…
l Spesso,
tutti i numeri che il computer usa
sono multipli di quattro cifre
l à Chiedete il perche’ a S. Orlando…
l Cioe’, ad esempio,
“1011” e “10111101”
l à possiamo vedere, in virtu’ del sistema
posizionale, questi blocchi di quattro cifre
come altrettante cifre
ESADECIMALE
l
l
l
Quattro cifre binarie possono rappresentare sedici
valori diversi (da “0000” a “1111”)
à Possiamo usare un sistema numerico a sedici
cifre (cosiddetto ESADECIMALE, o HEX):
0, 1, …, 9, A, B, C, D, E, F
Cosi’, ad esempio,
“1011” binario e’ uguale a “B” esadecimale
“10111101” si puo’ vedere come “1011 1101”, e
quindi come “BD”
MORALE
l Il
computer usa il sistema binario
l Molto spesso, siccome i numeri utilizzati
sono multipli di quattro cifre, conviene
usare la numerazione esadecimale, che e’
MOLTO PIU’ COMPATTA, visto che in
ogni caso e’ molto facile passare dall’una
all’altra numerazione
MEMORIA
l
l
l
l
La MEMORIA del computer e’ una serie di
contenitori per numeri
Ogni contenitore contiene un numero, che e’
limitato (tipicamente, 8 cifre binarie, un BYTE)
Per identificare tali contenitori, si usano
identificatori, detti INDIRIZZI di memoria
Spesso, tali indirizzi sono numeri, ad esempio 0, 1,
2, 3, 500, 101110112, A0BC2Ehex
Linguaggio Macchina
l Il
LINGUAGGIO MACCHINA e’ il
linguaggio che il computer usa per eseguire
istruzioni e manipolare dati
COME E’ FATTO
l Tipico
programma in linguaggio macchina:
41471F0A470B980DBE190EF517C6120B
7408640F18D651826C4321362846AA106
BF5108561086431FF846B20001818282D8
21864654147101027126F45B6182012C08
4A7184628196C31468156D818281B4F72
14612641A26C282B82B919828646B1D49
PROGRAMMI come DATI
l Il
Computer vede tutto come DATI
(numeri).
l Volendo, puo’ vedere certi dati come
corrispondenti a istruzioni (il cosiddetto
LINGUAGGIO MACCHINA)
l Ad esempio, “342156” potrebbe voler
significare “somma uno al valore del
registro t0”
PRIMI COMMENTI
l Aiuto!!
l Ma
e’ illeggibile!
Linguaggio macchina
per noi umani…?
l
l
l
l
l
Leggere “numeri” non e’ molto facile…
Per noi umani, conviene tradurre questi codici
numerici in qualcosa di piu’ leggibile
Ad esempio, “342156” potrebbe tradursi in forma
piu’ leggibile con “add t0, 1” (somma 1 al registro
t0)
à tale formato piu’ leggibile e’ detto
LINGUAGGIO ASSEMBLY
Spesso, vista la stretta corrispondenza, si fa
confusione, o si considerano i due termini uguali
Linguaggio Assembly
l
l
l
Il linguaggio assembly e’ un linguaggio di
programmazione, che rispecchia fedelmente le
istruzioni del linguaggio macchina
USO: piu’ leggibile, piu’ flessibile
NOTA: proprio perche’ un assembly puo’
aggiungere funzionalita’, ci possono essere
MOLTI LINGUAGGI ASSEMBLY DIVERSI
per lo stesso linguaggio macchina (anche se,
ovviamente, con differenze minime)
Tornando al linguaggio
macchina…
l Un
programma in linguaggio macchina e’
dunque una sequenza di dati
l Esso risiede nella MEMORIA ESTERNA
del computer
Come distinguere?
l C’e’
una locazione di memoria speciale, il
cosiddetto PROGRAM POINTER, che
contiene un indirizzo di memoria. Il dato
corrispondente a tale indirizzo, viene
considerato dal processore come una
istruzione in linguaggio macchina
Che operazioni?
l Le
tipiche operazioni di un linguaggio
macchina riguardano:
l Il movimento di dati
l La manipolazione di dati
l Il flusso di istruzioni
Il movimento di dati
l Da
una parte della memoria all’altra della
memoria
DUE MEMORIE (almeno)
Interna ed esterna
Interna al processore: molto veloce, ma
piccola e limitata
Esterna al processore: piu’ lenta, ma molto
grande ed estendibile
MEMORIA INTERNA
l Data
la piccola taglia (e le particolari
funzionalita’), di solito si usano indirizzi
con nomi speciali, detti REGISTRI (a0, a1,
t0, t1, ..)
MEMORIA ESTERNA
l Vista
la grande taglia, si usano numeri per
identificarla (0, 1, 2, 3, …)
l Usare numeri ha anche il vantaggio,
fondamentale, che si possono usare tutte le
operazioni aritmetiche per manipolare
indirizzi di memoria
OPERAZIONI TIPICHE
l Si
usano per passare dati dalla memoria
interna (registri) alla memoria esterna, e
viceversa:
l LOAD
l STORE
LOAD
l LOAD
(letteralmente “carica”), prende il
valore da un indirizzo di memoria esterna, e
lo carica nella memoria interna
l Forma tipica:
LOAD registro indirizzo
carica il valore dell’indirizzo specificato nel
registro
STORE
l STORE
(letteralmente “immagazzina”),
scrive un certo valore nell’indirizzo di
memoria specificato
l Forma tipica:
STORE valore indirizzo
scrive il valore all’indirizzo specificato
LA MANIPOLAZIONE DI DATI
l Tipicamente,
si puo’ agire con le operazioni
aritmetiche (+, -, *, /), ed altre operazioni di
natura simile
Il flusso di istruzioni
l Abbiamo
detto che e’ grazie al program
pointer che il computer sa quale istruzione
codificare
l Ma una volta codificata, cosa fare?
l à tipicamente, si porta automaticamente il
program pointer all’indirizzo successivo
Il flusso di istruzioni (cont.)
l
l
l
Se non potessimo modificare questo flusso, il
programma verrebbe allora sempre eseguito come
una linea, in sequenza
Purtroppo, come mostreremo in un’altra lezione,
questo sarebbe troppo limitativo: ogni istruzione
verrebbe eseguita SOLO UNA VOLTA (!)
à ci sono opportune istruzioni che permettono di
modificare il program pointer, cioe’ di modificare
il flusso di istruzioni, di modo da permettere ad
esempio cicli e salti