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