Un po' di storia • Il primo strumento di calcolo utilizzato nell'antichità da Greci e Romani fu l'abaco. Un po' di storia • Le prime macchine calcolatrici (eseguivano calcoli in maniera automatica) vennero costruite per risolvere problemi specifici. • Queste macchine erano di tipo meccanico e si basavano su un funzionamento simile a quello degli orologi, con ruote dentate ed ingranaggi. (par. 6.1) Un po' di storia Un po' di storia • La prima macchina da calcolo è del 1623, costruita da Wilhelm Schickard (1592-1635, matematico ed astronomo tedesco): eseguiva le quattro operazioni. • Blaise Pascal (1623-1662, francese) costruì una macchina che eseguiva solo somme e sottrazioni e che utilizzava le dieci cifre decimali. (Linguaggio Pascal di Niklaus Wirth 1970). • John Napier (Neper, 1550-1617, scozzese), il matematico che inventò i logaritmi, costruì una macchina (detta “gli ossicini di Nepero”) che trasformava le moltiplicazioni e le divisioni in somme e sottrazioni. • Gottfried Wilhelm Leibnitz (1646-1716, tedesco) costruì una macchina che eseguiva anche le moltiplicazioni e le divisioni. 1 Leibnitz ideò il sistema numerico binario Un po' di storia • Charles Babbage (1791-1871, inglese), ispirandosi ai telai di Joseph-Marie Jacquard (1752-1834, francese) (schede perforate che riproducevano disegni ripetuti ciclicamente), ideò una macchina, detta “alle differenze”, con la quale si potevano costruire tavole numeriche e una, detta “analitica”, alla quale si dovevano fornire schede perforate contenenti sia i dati da elaborare che le regole (istruzioni) di calcolo da eseguire. Un po' di storia • Georg Scheutz (1785-1873, svedese) si occupava di tecniche tipografiche e realizzò la parte stampante della macchina da calcolo; costruì una macchina simile a quella di Babbage, che fu acquistata dall'osservatorio astronomico di Albany (stato di New York) per costruire delle tavole con cui calcolare la posizione degli astri. Un po' di storia • Per programma (algoritmo) si intende una sequenza di istruzioni da far eseguire ad una macchina. • Chi fu il primo programmatore? 2 Un po' di storia • Ada Augusta Byron contessa di Lovelace (1815-1852, inglese), figlia del poeta Lord Byron. Ada aveva avuto una educazione matematica e collaborava con matematici dell'epoca come De Morgan. Ella scrisse una sequenza di istruzioni (programma) per la macchina di Babbage, con le quali si potevano calcolare numeri di Bernoulli. Linguaggio Ada concorrente. (1979): programmazione Nuove invenzioni alla fine del secolo diciannovesimo • La macchina da scrivere. • Il comptometro, dello statunitense D. E. Felt: prima calcolatrice da tavolo provvista di tasti per introdurre i dati. • La macchina a schede perforate, dello statunitense Hermann Hollerit: • usava l'elettricità, venne utilizzata in Canada nel 1890 per il censimento. • Hollerit nel 1896 fondò la Tabulating Machine Company che nel 1924 divenne la IBM (International Business Machines). Il primo calcolatore Il primo calcolatore • Konrad Zuse, tedesco, costruì nel 1938 una calcolatrice meccanica, chiamata Z1. • Successivamente nel 1941 costruì lo Z3, un calcolatore elettromeccanico considerato il primo calcolatore. – Zuse utilizzò il relè che poteva avere solo due posizioni, pertanto abbandonò il sistema decimale (ruote dentate potevano essere numerate) e passò al sistema binario. 3 Il primo calcolatore • Nel 1944 Howard Aiken, dell'università di Harvard, costruì (indipendentemente) il suo primo calcolatore elettromeccanico Mark I. – Mark I usava il sistema decimale e le schede perforate: aveva l'aspetto di un armadio, lungo 16 metri. Eseguiva 3 addizioni in un secondo, impiegava 6 secondi per una moltiplicazione e 12 per una divisione. – Modelli successivi: Mark II e Mark IV. Calcolatori moderni Calcolatori moderni I generazione (dalla metà degli anni '40 alla metà degli anni '50) • A differenza delle prime macchine, i calcolatori moderni sono macchine universali, perché realizzano applicazioni diverse. • E' l'epoca delle valvole termoioniche. • ENIAC (Electronic Numerical Integrator And Computer, integratore numerico e calcolatore elettronico), progettato presso l'università della Pennsylvania (1945-47). • Con l'evoluzione della tecnologia i calcolatori sono così cambiati che si distinguono generazioni successive di macchine. • Occupava una grande stanza ed era costituito da molti armadi con circa 18000 valvole, parecchie delle quali si bruciavano ogni giorno e dovevano essere sostituite; veniva programmato collegando cavi su appositi pannelli, simili a quelli dei centralini telefonici, ogni specifico problema richiedeva un diverso collegamento dei cavi; eseguiva 5000 addizioni al secondo. 4 L’ENIAC I generazione (dalla metà degli anni '40 alla metà degli anni '50) • L'ungherese J. Von Neumann progettò nel 1946 la macchina EDVAC e poi lo IAS. • IAS: le componenti erano organizzate secondo una architettura presente ancora oggi sui calcolatori: architettura di von Neumann. II generazione (dalla metà degli anni '50 alla prima metà degli anni '60) • E' l'epoca dei transistor, molto più piccoli e meno costosi delle valvole termoioniche. • In questo periodo si ha lo sviluppo del software: si costruiscono i primi linguaggi ad alto livello e i primi sistemi operativi. III generazione (fino ai primi anni '70) • E' l'epoca dei circuiti integrati: una componente unica contiene centinaia di transistor. • Si passa ai circuiti integrati su larga scala: LSI (Large Scale Integration) con migliaia di transistor. • Nel 1969 M. E. Hoff, ingegnere della Intel, riuscì a ridurre le dimensioni della CPU fino a qualche centimetro, ottenendo i cosiddetti chip (microprocessori). 5 IV generazione (attuale) • E' l'epoca dei circuiti integrati su scala molto larga (VLSI: Very Large Scale Integration) e dei circuiti integrati su scala ultra-larga (ULSI: Ultra Large Scale Integration) contenenti milioni di transistor. V generazione (attuale) • Tecnologia WSI (Wafer Scale Integration) con dispositivi ancora più piccoli e con decine di milioni di dispositivi su un unico chip (wafer perché sono costituiti da più strati). • Il chip del Pentium 4 contiene 50 milioni di transistor. • Calcolatori con architetture parallele. I Chip • I chip (pezzetto) sono sottili lamine di silicio (dopo l'ossigeno è l'elemento più diffuso) che contengono milioni di interruttori che realizzano i due stati acceso/spento e che sono collegati da tracce di alluminio come dei sottilissimi fili dello spessore di mezzo micron (1µ = 10-9 m., un capello è dello spessore di 100 µ). • Case costruttrici: Intel, Motorola, Apple, Digital, Sun, ... I Chip • I chip sono piccoli, costano poco, sono molto potenti e facilmente costruibili. • Costruzione di un chip: • progettazione del disegno di tutti i collegamenti tra i milioni di transistor; • costruzione di maschere: le maschere sono lamine di quarzo sulle quali viene inciso il disegno (una maschera per ogni strato del chip), e che viene fotografato su una fetta di silicio; (par. 6.2) 6 I Chip • controllo di ogni fetta: vengono controllati centinaia di chip e le parti difettose vengono marcate; • rivestimento: le fette vengono tagliate in pezzetti (chip) che poi vengono rivestiti (il rivestimento serve sia per protezione che per costruire dei collegamenti con le altre componenti) e alloggiati in un contenitori di plastica o ceramica . Lo sviluppo teorico Lo sviluppo teorico La teoria della calcolabilità • Con l'evoluzione tecnologica delle macchine da calcolo si ha parallelamente un aumento dei problemi che si vogliono far risolvere ai calcolatori: di molti problemi si cerca la soluzione per via numerica (integrali, sistemi, equazioni differenziali, ...). • Qualsiasi problema può essere risolto tramite un programma? • Il matematico e logico Alan Turing (19121954, inglese), inventore della teoria della calcolabilità, definì il concetto di funzione calcolabile e ideò un modello astratto di calcolatore (Macchina di Turing) nel quale la computazione è rappresentata da una sequenza di trasformazioni di stato. • Egli scoprì che esistono problemi indecidibili: problemi per i quali non esiste un algoritmo in grado di risolverli. 7 Computer e Programma • Un computer è una macchina che Computer e Programma – memorizza dati (numeri, parole, immagini, suoni...) – interagisce con dispositivi (schermo, tastiera, mouse...) – esegue programmi • Un programma è una sequenza di istruzioni che il computer esegue e di decisioni che il computer prende per svolgere una certa attività. Programmi e istruzioni Cos’è la programmazione? • Nonostante i programmi siano molto sofisticati e svolgano funzioni molto complesse, le istruzioni di cui sono composti sono molto elementari, ad esempio • Un programma descrive al computer, in dettaglio, la sequenza dei passi necessari per svolgere un particolare compito. • L'attività di progettare e realizzare un programma è detta programmazione. • Usare un computer non richiede alcuna attività di programmazione (così come per guidare una automobile non è necessario essere un meccanico). • Un informatico professionista solitamente svolge una intensa attività di programmazione. • • • • estrarre un numero da una posizione della memoria sommare due numeri inviare la lettera A alla stampante se un dato è negativo, proseguire l'esecuzione del programma da una certa istruzione anziché dalla successiva (decisione). 8 Problemi Problemi da risolvere • Quale tipo di problemi è possibile risolvere con un computer? • Dato un insieme di fotografie di paesaggi, qual è il paesaggio più rilassante? • Avendo depositato ventimila euro in un conto bancario che produce il 2% di interessi all’anno, capitalizzati annualmente, quanti anni occorrono affinché il saldo del conto arrivi al doppio della cifra iniziale? • Il primo problema non può essere risolto dal computer. Perché? Problemi • Il primo problema non può essere risolto dal computer perché non esiste una definizione di paesaggio rilassante che possa essere usata per confrontare in modo univoco due paesaggi diversi. • Un computer può risolvere soltanto problemi che potrebbero essere risolti anche manualmente: è solo molto più veloce, non si annoia, non fa errori. Problemi • I problemi da risolvere sono di varia natura: – mettere in ordine alfabetico dei nomi di persone; – trovare gli zeri di una funzione f(x); – contare quante volte una parola compare all'interno di un testo; – gestire acquisti e prestiti dei libri di una biblioteca. • Il secondo problema è certamente risolvibile manualmente, facendo un po’ di calcoli... 9 Problemi e algoritmi • Indipendentemente da chi sarà l'esecutore (l'uomo o la macchina) la prima cosa da fare è: trovare l'algoritmo risolutivo, ossia la sequenza di operazioni che permette di passare dai dati ai risultati. Algoritmi • Un algoritmo (Al Kowarizmi, matematico persiano del IX secolo d. C.) è un procedimento di soluzione che gode delle seguenti proprietà: 1. è un insieme di operazioni eseguibili; 2. esiste una prima operazione; 3. dopo ogni operazione è individuata la successiva; 4. esiste un'ultima operazione. Algoritmi Algoritmi: operazione eseguibile • non è ambigua, è univocamente interpretabile da un esecutore (uomo o macchina): • le operazioni tra numeri hanno un simbolo non ambiguo: • 2*3 (prodotto) • 2p3 è ambigua 2+3 (somma) p: per o più • è effettiva, l'esecutore deve poterla svolgere in un tempo finito: • somma di due numeri interi: sì • calcolo di un limite: no (concetto di infinito) (par.1.2) 10 Algoritmi Algoritmi • Le proprietà 2. e 4. rappresentano la finitezza: un algoritmo deve terminare in un tempo finito. • La proprietà 3. dice che l'algoritmo è deterministico: ad ogni passo è univocamente individuato il passo successivo. • Si possono ideare algoritmi non deterministici: • ad ogni passo c'è più di una scelta e l'algoritmo individua tra le scelte quella che porterà alla soluzione. • simulazione: si può pensare ad una esecuzione contemporanea delle scelte. Algoritmi Algoritmi • Problema: Avendo depositato ventimila euro in un conto bancario che produce il 2% di interessi all’anno, capitalizzati annualmente, quanti anni occorrono affinché il saldo del conto arrivi al doppio della cifra iniziale? Algoritmo: 1. L'anno attuale è 0; il saldo attuale è 20000 euro 2. Ripetere i passi 3. e 4. finché il saldo attuale è minore di 40000, quindi passare al passo 5 3. Aggiungere 1 al valore dell'anno 4. Il nuovo saldo attuale è il valore del saldo attuale moltiplicato per 1.02 (1 + 2/100) 5. Il risultato è il valore dell'anno attuale 11 Algoritmi Algoritmi • Ogni operazione è eseguibile: somme e prodotti (effettive e non ambigue) • I valori delle variabili (anno, saldo, interesse) sono effettivi: • Se vogliamo fare eseguire l'algoritmo da un calcolatore, dobbiamo trasformare la sequenza di istruzioni in una sequenza scritta in un linguaggio comprensibile alla macchina: programma, codice. • I primi programmi erano scritti in linguaggio macchina (o codice binario, ossia una sequenza di simboli 0 e 1). • se l'interesse dipendesse da parametri noti solo nel futuro non calcolabili a priori non potremmo eseguire l'aggiornamento del saldo. • E' finito perché il 2% di 20000 euro sono 400 euro e quindi al più dopo cinquanta anni si raggiunge il saldo desiderato: il ciclo termina. Algoritmo → Programma Algoritmo →Programma • Nel corso degli anni si sono sviluppati vari linguaggi; si è passati da quelli cosiddetti a • basso livello, perché più vicini alla macchina, come Assembler • a quelli detti ad • alto livello, perché più vicini all’uomo come Pascal, C, Java. 12 Algoritmo → Programma Analisi • La risoluzione avviene in due passi: • Analisi: problema → algoritmo • Codifica: algoritmo → programma (codice) • Per far eseguire il programma al calcolatore occorre imparare ad usare quei programmi che ne gestiscono le risorse (implementazione): • editor di testo, compilatore, esecutore, funzioni del sistema operativo; test di funzionamento. • Occorre inventare il procedimento di soluzione che sarà indipendente (o quasi) dal linguaggio di programmazione; si distinguono due fasi: • definizione del problema: individuare la struttura dati più idonea, risolvere un problema generale; • progettazione del programma: individuare le istruzioni e l'ordine di esecuzione; si procede dal problema generale e si scende nei particolari; si può utilizzare un linguaggio di pseudocodifica. (par. 1.3) Codifica Programma • Occorre trasformare le istruzioni in frasi comprensibili al calcolatore; si deve imparare un linguaggio di programmazione. • Noi studieremo il linguaggio C++. • Un buon programma deve essere facilmente utilizzato da altri, deve durare nel tempo, deve essere facilmente aggiornabile. • Come sistema operativo utilizzeremo Linux. • Verifica: • casi di prova e test di funzionamento • gestione di casi eccezionali • controllo della terminazione. • Documentazione: • inserire delle frasi di commento che spieghino “cosa fa” il programma. 13 Risorse di un calcolatore • Risorse hardware: Risorse di un calcolatore • componenti fisiche • Risorse software: • programmi di gestione e applicativi • Risorse firmware: • componenti hardware specifiche funzioni preprogrammate per (par. 6.4) Risorse hardware Risorse hardware • Unità centrale: l'unità di elaborazione centrale (CPU) e la memoria centrale o primaria. • Memorie secondarie o ausiliarie o di massa. • Dispositivi di ingresso/uscita. • Connessioni e supporti: linee di collegamento (bus), scheda madre. 14 L'architettura di von Neumann • Ideata da Janos' (John) von Neumann: •L'elaboratore è dotato di una memoria nella quale vengono registrati sia i dati che i programmi da eseguire. •Il calcolatore diventa una “macchina universale”, perché riceve in ingresso (input) i dati e il programma e restituisce in uscita (output) i risultati (l’elaborazione dei dati eseguita dal programma). L'architettura di von Neumann CA CC C I M O R CA + CC M I O R = unità centrale di elaborazione = memoria centrale = dispositivi di ingresso = dispositivi di uscita = dispositivi di memoria ausiliaria L'architettura di von Neumann • La grande maggioranza degli elaboratori odierni ha una architettura che può essere (più o meno facilmente) ricondotta al modello di von Neumann: • le eccezioni più importanti sono alcune macchine ad elaborazione parallela. • Il modello è importante perché semplificò l’architettura dell’hardware rendendolo omogeneo. La Memoria primaria 15 La Memoria primaria La memoria primaria si compone di due parti: • ROM (Read Only Memory) • RAM (Random Access Memory) La memoria ROM • È una memoria a sola lettura: • costituita da celle nelle quali non è possibile immagazzinare nuovi dati, ma dalle quali si possono estrarre informazioni (lettura). • È ad accesso diretto (casuale) • Essa mantiene il suo contenuto a macchina spenta e contiene i programmi eseguiti all'accensione del sistema: • test di funzionamento, caricamento del software di base, BIOS (Basic Input/Output System) • Tali informazioni (firmware) vengono inserite dalla ditta costruttrice. La memoria RAM La memoria • È il dispositivo nel quale si possono immettere, conservare, estrarre le informazioni da elaborare: il programma e i dati • Il byte è l'unità di misura della capacità della memoria • chip di memoria realizzati con la stessa tecnologia (al silicio) utilizzata per la CPU. • 1Kbyte (kilobyte): • 1Mbyte (megabyte): • L'informazione elementare (unità minima di informazione) si chiama bit (binary digit) o cifra binaria. • Rappresenta i due stati di un circuito “aperto” e “chiuso”, convenzionalmente detti 0 e 1, o anche “falso” e “vero”. • 1Gbyte (gigabyte): • 1Tbyte (terabyte): 210 byte = 1024 byte ~ 103 byte 220 byte = 1 048 576 byte ~ 106 byte 230 byte =1 073 741 824 byte ~ 109 byte 240 byte ~ 1012 byte (mille miliardi) • RAM 512 Mbyte …. vari Giga … 16 La memoria RAM • La memoria è organizzata a gruppi di bit (solitamente 8) chiamati byte. • La memoria è costituita da un numero finito m di celle, o locazioni di memoria, tutte della stessa dimensione. • Ogni cella è composta da un numero n predefinito di bit • n = 8, 16, 32, 64 quindi 1, 2, 4, 8 byte. • Il contenuto di una cella di memoria si chiama parola (word): è un numero binario fisicamente memorizzato all'interno di essa. La memoria RAM Ogni cella è individuata da un indirizzo. L’indirizzo di memoria è un numero naturale progressivo (0, ..., m-1) che individua ogni cella in maniera univoca all’interno della memoria stessa. Lo spazio di indirizzamento è l'insieme di tutti gli indirizzi possibili delle celle di memoria: • dipende dal numero di bit destinati a rappresentare un indirizzo; • ogni bit può assumere due valori, quindi con k bit si possono rappresentare 2k indirizzi diversi, k=16, 32, 64. La memoria RAM La memoria RAM • Lo spazio di memoria è la quantità di memoria disponibile. Dipende dal numero di indirizzi e dalla grandezza delle celle. • Accedere ad un dato significa selezionare mediante l'indirizzo la cella in cui è memorizzato e prelevarne il valore (lettura). • Memorizzare un dato significa selezionare mediante l'indirizzo la cella in cui si intende introdurlo ed introdurre il dato (scrittura). • Si chiama tempo di accesso il tempo che intercorre tra l'istante in cui si richiede l'informazione e l'istante in cui tale informazione è disponibile. • Si chiama ciclo di memoria il tempo minimo richiesto tra due accessi consecutivi. • Viene misurato in nanosecondi (ns = 10-9 secondi); si hanno cicli di memoria anche inferiori ai 30 ns. 17 La memoria RAM • È una memoria ad accesso diretto (casuale) • il tempo di accesso è lo stesso per ogni indirizzo • È costituita da celle nelle quali è possibile estrarre e registrare nuove informazioni (lettura e scrittura). • È una memoria volatile • perde il suo contenuto quando la macchina viene spenta. • Nella RAM si scrivono le istruzioni che compongono i programmi e i dati. • La RAM è veloce e costosa. Altre memorie • Memoria cache • area di memoria ad accesso veloce, localizzata tra CPU e RAM, utilizzata per contenere dati e istruzioni di prossimo utilizzo da parte del processore (frigorifero). • Il caricamento dei dati è sequenziale • Memoria buffer • area di memoria temporanea utilizzata nei collegamenti tra dispositivi di diversa velocità (tra CPU e tastiera, video, stampante): • salvare gli ultimi comandi usati • operazioni di copia/incolla Altre memorie • La quantità di RAM limita le dimensioni dei programmi e dei dati che sono direttamente accessibili. • Memorie virtuali: • se lo spazio di indirizzamento lo consente, si riesce a sfruttare anche lo spazio su disco (hard disk) in modo che i trasferimenti di informazioni risultino invisibili all'utente. Il sistema operativo vi memorizza parte dei dati e dei programmi non in uso, e quando questi sono necessari li trasferisce nella RAM. L'unità centrale di elaborazione CPU • La CPU (Central Processing Unit) esegue le istruzioni del programma, legge e scrive le informazioni nella memoria centrale, richiede servizi alle apparecchiature periferiche, è costituta da uno o più chip. • È composta da: • ALU: Arithmetic Logic Unit • Unità di controllo • registri 18 ALU: unità aritmetico-logica Unità di controllo • La ALU (Arithmetic Logic Unit) è la parte operativa: esegue le operazioni • Accede solo alle informazioni contenute nella memoria centrale ed ha il compito di gestire la successione delle operazioni da svolgere: • aritmetiche • addizione, sottrazione, moltiplicazione e divisione • logiche • confronti di valori • utilizza i valori depositati in appositi registri (celle di memoria ad accesso veloce per la memorizzazione temporanea dei dati). Principali registri della CPU • Contatore di programma (PC: Program Counter) – contiene l'indirizzo di memoria istruzione da caricare ed eseguire della successiva • Registro istruzioni (IR: Instruction Register) – contiene l'istruzione che deve essere interpretata ed eseguita • Registro dati – Contiene dati, risultati intermedi • Registro di stato • reperire dalla memoria le istruzioni (caricamento) • interpretarle (decodifica) • farle eseguire: caricare gli operandi, eseguire l'istruzione, memorizzare il risultato (esecuzione). Funzionamento della CPU • Il funzionamento è ciclico: • Ciclo fetch-decode-execute • fetch: caricamento dalla memoria dell'istruzione da eseguire e sua memorizzazione nel registro istruzioni; incremento di una unità del contatore di programma (istruzioni eseguite in sequenza) • decode: decodifica dell'istruzione da eseguire • execute: esecuzione dell'istruzione – Contiene segnalatori che indicano condizioni particolari • Overflow, risultato 0 o negativo 19 Clock Coprocessore • È un segnale che viene trasmesso ai vari circuiti per sincronizzarne il funzionamento: • Accanto alla CPU esistono altri processori con funzioni specifiche: • l'intervallo di tempo tra due impulsi successivi si chiama periodo di clock e viene misurato in Megahertz (MHz milioni di cicli al secondo), Gigahertz (miliardi di cicli al secondo) • si può dire che è la frequenza con cui il processore esegue le singole operazioni elementari • maggiore è la frequenza, più veloce è il processore all'interno della stessa famiglia. • processori diversi posso elaborare lo stesso numero di operazioni con periodi di clock diversi. • Coprocessore matematico che esegue i calcoli in virgola mobile, moltiplicazioni tra interi, … • Coprocessore grafico che gestisce le informazioni registrate nella memoria e le trasforma in grafica sullo schermo. I bus I bus • I bus sono linee di collegamento tra la CPU e la memoria centrale (bus interni) e le periferiche (bus esterni) • I bus sostituiscono l'insieme (complesso) dei collegamenti reciproci tra tutte le singole componenti. • I bus trasportano vari tipi di informazioni, la velocità del “traffico smaltito” dipende dal numero di bit (32, 64) che i bus riescono a trasportare simultaneamente. • Il bus è in realtà costituito da tre bus distinti: • bus dei dati • bus degli indirizzi (destinatario, mittente) • bus dei segnali di controllo • Sul bus dei dati viaggiano dati da e verso la CPU. • Sugli altri bus viaggiano indirizzi e segnali di controllo che provengono soltanto dalla CPU. CPU Memoria Memoria principale secondaria Dispositivi di Input e di Output Bus 20 Le memorie secondarie Le memorie secondarie • Sono dette anche memorie di massa o ausiliarie. • Hanno una funzione ed una realizzazione hardware diversa da quelle della memoria primaria • permettono di mantenere le informazioni anche a macchina spenta • sono meno costose • l'accesso è più lento • in alcune dipende dalla posizione del dato Le memorie secondarie • Unità a disco • Solitamente ad accesso diretto (Gbyte, Tbyte) • Disco rigido o hard disk • Disco flessibile o floppy disk • Dischi ottici • Nastri magnetici • Ad accesso sequenziale: il tempo di accesso dipende dalla posizione del dato Hard disk • Il disco rigido è composto da una pila di piatti rotanti rivestiti di un materiale magnetico. Ogni piatto è organizzato in tracce circolari concentriche, ciascuna traccia è divisa in settori (inizializzazione o formattazione). La testina di lettura/scrittura si sposta in senso radiale individuando univocamente la posizione. • Hanno elevata capacità, ma sono lenti; si utilizzano per copie di sicurezza. Sono a tecnologia magnetica. 21 Hard disk • è contenuto in una scatola sigillata per proteggerlo dalla polvere • programmi e dati risiedono sul disco rigido e vengono caricati nella RAM quando necessario, per poi tornarvi aggiornati se e quando necessario. Altre memorie secondarie • Nei dischetti lo strato magnetico è applicato su un supporto flessibile. • Nei dischi ottici la lettura avviene tramite un raggio laser ed un rilevatore del passaggio della luce (alcuni sono sequenziali con tracce a spirale, altri ad accesso diretto): • CD-ROM: Compact Disk Read Only Memory • usato per distribuire programmi o informazioni Altre memorie secondarie • CD-R (Compact Disk Recordable) • può essere scritto dall'utente una sola volta • CD-RW possono essere scritti più volte • DVD (Digital Video Disk, Digital Versatile Disk) • enorme capacità di memorizzazione • “chiavette” USB (o penne) in sostituzione del floppy • capacità superiore ai floppy (Gbyte). Principali dispositivi di ingresso • • • • • • • Tastiera Mouse Trackball Joystick Microfono Scanner Penna luminosa 22 Principali dispositivi per l'uscita • • • • Video (schermo) Stampante Plotter Altoparlanti La scheda madre • La scheda madre (mother-board) situata all'interno di un Personal Computer contiene la memoria primaria, la CPU, i bus, gli alloggiamenti (slot) di espansione, le porte per il controllo delle periferiche. La scheda madre La scheda madre di un PC CPU slot Rappresentazione delle informazioni RAM 23 Rappresentazione delle informazioni • L’informatica si occupa di rappresentare ed elaborare informazioni: • numeri • caratteri • audio • immagini • video Rappresentazione dei caratteri I caratteri I caratteri • I caratteri appartenenti ad un alfabeto vengono codificati (cioè “rappresentati”) mediante sequenze di bit: una diversa sequenza per ciascun diverso carattere. • Uno dei codici più noti e usati è il codice ASCII (American Standard Code for Information Interchange): • Dato che l’unità elementare di informazione nei calcolatori è il byte (= 8 bit), si è passati ad usare, quasi sempre, il codice ASCII esteso, che usa una sequenza di 8 bit per ciascun carattere degli alfabeti occidentali: • usa una sequenza di 7 bit per ciascun carattere: ci sono 128 (=27) sequenze diverse, utilizzate anche per lettere, segni di punteggiatura, cifre decimali, ecc. • ci sono 256 (=28) sequenze diverse, utilizzate anche per vocali accentate e altre lettere speciali (es. ß tedesca, ç francese) • le sequenze con la prima cifra uguale a zero coincidono con il codice ASCII (par. 6.9) 24 I caratteri I caratteri (codice Unicode) • I primi 32 caratteri del codice ASCII (con codice da 0 a 31) sono caratteri di controllo: • Per rappresentare i segni grafici utilizzati da tutti gli alfabeti del mondo servono molti più simboli diversi. • • • 9 tabulatore 10 nuova riga 13 invio ’\t’ ’\n’ ’\r’ • I caratteri da 32 a 127 sono caratteri stampabili: • 32 spazio ’’ • da 48 a 57 caratteri numerici, le cifre decimali ’0’, ’1’… • da 65 a 90, da 97 a 122 caratteri alfabetici (maiuscoli e minuscoli) • da 33 a 47, da 58 a 64, da 91 a 96, da 123 a 127 caratteri di interpunzione. • Codifica Unicode http://www.unicode.org • usa una sequenza di 16 bit segno grafico: per ciascun • ci sono 65536 (= 216) sequenze diverse • le sequenze con le prime otto cifre uguali a zero coincidono con il codice ASCII esteso. I caratteri (codice Unicode) Risorse software 25 Risorse software Software di base • Con la parola software si intende in generale un insieme di programmi. • Si distinguono però i programmi fatti dagli utenti dai programmi propri del calcolatore e che gli utenti utilizzano: • Il software di base è un insieme di programmi che permettono il funzionamento del calcolatore e il suo utilizzo da parte di utenti esterni. • Esso interagisce direttamente con l’hardware nascondendo all’utente la struttura fisica della macchina. • software di base • software applicativo • pacchetti di programmi che risolvono specifici problemi (“libreria”, “library - biblioteca”). (par. 6.7) Software di base • Le principali componenti sono: • Sistema operativo • programmi per il funzionamento del calcolatore; il S.O. è strettamente legato all’hardware • Interfaccia utente • permette la comunicazione con il sistema operativo: comandi da tastiera o da menu (grafica) Linguaggi di programmazione • Software di comunicazione • comunicazione tra calcolatori: reti locali o mondiali. 26 Linguaggi di programmazione Linguaggi di programmazione • I linguaggi di programmazione sono quei linguaggi in cui si devono esprimere le istruzioni che si vogliono elaborare. • Nei linguaggi di programmazione si distinguono dei livelli e delle generazioni: • generazioni: le varie generazioni si distinguono in base ai concetti che sono stati successivamente introdotti • basso livello: • I generazione: linguaggio macchina • II generazione: linguaggi tipo Assembler • alto livello • III generazione: linguaggi procedurali (imperativi) Fortran, Pascal, C, Java, … • IV generazione: linguaggi logici (Prolog) e funzionali (Lisp) • livello basso livello “vicini” alla macchina alto livello “vicini” all’uomo (par. 4.1) Linguaggi di programmazione Linguaggi di programmazione • I linguaggi procedurali sono linguaggi in cui si individuano gruppi di istruzioni (procedure) che risolvono un problema specifico; sono detti anche imperativi perché le istruzioni eseguono comandi di assegnazione di valori nella memoria. • Il passaggio dai linguaggi a basso livello a quelli ad alto livello si ha con l’introduzione del concetto di variabile: in tale modo si ha l’indipendenza dalla locazione di memoria. • Successivamente sono stati introdotti i concetti di tipo di dato e di tipo di dato astratto (linguaggi a oggetti). • Nei linguaggi ad alto livello si hanno le strutture di controllo che permettono di regolare il flusso delle operazioni da eseguire. 27 Le istruzioni macchina Programmazione in linguaggio macchina • Le istruzioni elementari eseguite da un computer (cioè dalla sua CPU) si chiamano istruzioni macchina. • L’insieme di istruzioni macchina (instruction set) è specifico di una particolare CPU (CPU diverse hanno un diverso insieme di istruzioni). Le istruzioni macchina Le istruzioni macchina • I primi programmi erano scritti in linguaggio macchina e quindi un programmatore doveva conoscere tutti i codici numerici delle istruzioni macchina, oltre alle istruzioni che costituivano l’algoritmo risolutivo. • Nel linguaggio macchina le istruzioni sono scritte in codice binario (sequenze di 0 e 1); sono pertanto difficili da scrivere e poco leggibili. • Esempio. Supponiamo di voler confrontare due numeri, il primo è memorizzato in una variabile di nome a, il secondo è il valore costante 100, e vogliamo esprimere questa situazione: se a > 100 allora stampa “ERRORE” 28 Le istruzioni macchina Le istruzioni macchina • Le istruzioni macchina dovranno rappresentare una sequenza di operazioni di questo tipo: • In tutte le CPU, le istruzioni macchina si possono suddividere nelle seguenti categorie (i nomi delle istruzioni sono solo degli esempi) • carica in un registro il valore contenuto nella posizione di memoria 40 (numero naturale) • nel linguaggio macchina non esiste il concetto di variabile, ma solo la locazione di memoria individuata da un indirizzo • carica in un altro registro il valore 100 • se il primo valore è maggiore del secondo, prosegui con l’istruzione contenuta nella posizione di memoria 240 • trasferimento dati, tra i registri e la memoria principale • LOAD (verso un registro), STORE (verso la memoria) • operazioni aritmetiche e logiche, eseguite dalla ALU • aritmetiche: ADD, SUB, MUL, DIV • logiche: AND, OR, NOT Le istruzioni macchina • salti, per alterare il flusso di esecuzione sequenziale (viene modificato il Program Counter) • incondizionato (JUMP): salta in ogni caso • condizionato: salta solo se un certo valore è zero (JZ) o se è maggiore di zero (JGZ) Linguaggio Assembler 29 Linguaggio Assembler Assemblatore • Si utilizzano dei nomi simbolici per rappresentare le operazioni da eseguire e per rappresentare le locazioni di memoria: • Utilizzando l’assemblatore, il programmatore scrive il programma mediante dei nomi abbreviati (codici mnemonici) per le istruzioni macchina: il programma diventa più facile da scrivere e da leggere . • Il programma assemblatore si occupa poi di tradurre il programma in configurazioni di bit. • Tali linguaggi con codici mnemonici si dicono linguaggi assembly (uno diverso per ogni CPU). istruzioni assembler istruzioni macchina corrispondenza biunivoca I linguaggi assembly • Problema: occorrono molte istruzioni per eseguire anche le operazioni più semplici • Problema: la sequenza di istruzioni di uno stesso programma cambia al cambiare della CPU • è molto costoso scrivere programmi che possano funzionare su diverse CPU, perché praticamente bisogna riscriverli completamente Linguaggi di programmazione ad alto livello 30 Linguaggi ad alto livello Linguaggi ad alto livello • Negli anni ‘50 furono inventati i primi linguaggi di programmazione ad alto livello • Il programmatore esprime la sequenza di operazioni da compiere, senza scendere al livello di dettaglio delle istruzioni macchina. • FORTRAN (1956): primo “vero” linguaggio • BASIC, COBOL • Anni ‘60 e ‘70: programmazione strutturata • Pascal (Niklaus Wirth, 1968) • C (Brian Kernigham e Dennis Ritchie, 1970-75) • Anni ‘80 e ‘90, programmazione orientata agli oggetti • C++ (Bjarne Stroustrup) • Java (James Gosling e Patrick Naughton, 1991) (par. 6.7.5) • C++: if(a>100) cout<<"Errore\n"; • Java: if(a>100) System.out.println("Errore"); Linguaggi ad alto livello • Pascal: if a>100 then writeln ('Errore'); • Fortan if(a.gt.100) then write(6,*) 'Errore' Traduzione in linguaggio macchina endif Nel Fortan l’istruzione deve essere scritta su righe diverse. 31 Traduzione in linguaggio macchina • Le istruzioni scritte in un linguaggio ad alto livello non sono comprensibili alla macchina; occorre pertanto tradurle. • Si hanno due tipi di traduttori: • interpreti • compilatori (par. 6.7) Compilatore • Sia X un linguaggio. Un compilatore per X è un programma che riceve in ingresso un programma scritto in X, lo traduce in una sequenza di istruzioni scritte in linguaggio macchina (codice oggetto) ed esegue dei controlli: • analisi lessicale, sintattica, semantica. Interprete • L’interprete traduce ogni istruzione del programma sorgente e la esegue (Basic, Perl). • Gli interpreti sono programmi semplici. • Un programma scritto in un linguaggio con interprete ha una gestione poco efficiente perché ogni volta che si esegue il programma, le istruzioni devono essere tradotte nuovamente (esempio: errori di scrittura, esecuzione su nuovi dati). Compilatore • Analisi lessicale: • Si verifica che le parole del programma siano scritte correttamente secondo le regole del linguaggio. • Analisi sintattica: • Si verifica che le frasi del linguaggio siano scritte correttamente. • Analisi semantica: • Si verifica che la frase abbia significato (coerenza). 32 Compilatore e linker Portabilità ed efficienza • Se la compilazione ha avuto buon esito, un altro programma (linker) prende il codice oggetto, esegue gli agganci necessari (con moduli di libreria e moduli oggetto scritti dall’utente) e produce un “codice eseguibile”. • Il codice eseguibile (comprensibile alla macchina) viene elaborato (programma in esecuzione). • I linguaggi intrepretati sono portabili a livello di codice sorgente: possono essere eseguiti su macchine con diverse CPU. Sono poco efficienti per l’implementazione. • I linguaggi compilati sono portabili a livello di codice sorgente, ma non a livello di codice macchina, che dipende dalla CPU. Sono efficienti perché permettono di correggere gli errori prima dell’esecuzione e la traduzione è fatta una sola volta per prove diverse. • In alcuni linguaggi compilazione e link sono in un solo passo. Le fasi della programmazione Le fasi della programmazione • L’attività di programmazione si esegue in tre fasi: • scrittura del programma (codice sorgente) • compilazione del codice sorgente e creazione del codice eseguibile (codice macchina) • esecuzione del programma. 33 Le fasi della programmazione Le fasi della programmazione • Per scrivere il codice sorgente si usa un editor di testo, salvando (memorizzando) il codice in un file: ad esempio in un file di nome primo.c • Per compilare, richiamiamo il compilatore C++ scrivendo il comando • Solitamente si hanno a disposizione più editor richiamabili o tramite icona, o con comandi espressamente scritti, ad esempio: gedit primo.c g++ -o primo primo.c • Un generico comando di Linux è del tipo: nomecomando –opzioni argomenti • Nel nostro caso: • g++ è il nome del comando che chiama il compilatore C++ • -o è l’opzione che permette di sceglire il nome del codice eseguibile • primo è il nome del codice eseguibile • primo.c è il nome del file che deve essere compilato. Le fasi della programmazione Le fasi della programmazione • Se la compilazione non ha dato errori, l’uscita del compilatore è un file di nome primo • Cosa fare in caso di errori. • Se ci sono errori in compilazione, questi devono essere corretti altrimenti non si può passare alla fase successiva di esecuzione. Il compilatore evidenzia l’errore (o quasi) scrivendo la riga in cui si trova e il tipo di errore. • Corretti gli errori si procede ad eseguire un collaudo sul programma per testarne il buon funzionamento. • È un file contenente codice binario; con il comando g++ si effettua anche il passo di link (collegamento con altri moduli e con le librerie). • Per mandare in esecuzione si scrive il comando ./primo 34 Il processo di programmazione codice sorgente librerie compilatore (caricatore) codice sorgente compilatore codice sorgente librerie file di bytecode librerie interprete file eseguibile interprete programma in esecuzione programma in esecuzione programma in esecuzione linguaggio Java linguaggi compilati linguaggi interpretati Il linguaggio C++ Il linguaggio C++ Alfabeto • Il linguaggio C++ (Bjarne Stroustrup 1983) è una estensione del linguaggio C perché possiede i costrutti della programmazione ad oggetti: classi e specifiche per gestire ereditarietà, eccezioni, ecc. • Nel C++ sono state introdotte alcune modifiche per facilitare le operazioni di ingresso e uscita (ampliamento della libreria standard con i flussi di I/O). • Lo standard del linguaggio è del 1998; sono state eseguiti successivi ampliamenti presenti in (quasi) tutti i compilatori C++. • L’insieme dei caratteri usato è costituito dal codice ASCII esteso. • Le parole chiave, gli identificatori, i simboli del linguaggio sono costruiti utilizzando solo i primi 128 caratteri (ASCII standard): spazio, cifre, lettere maiuscole e minuscole, simboli speciali: (){}[],.:;?!%\|/+-*"'<>=#& (Cap. 13) (par. 13.1) 35 Identificatori e Parole chiave Regole per costruire i nomi • Si chiamano identificatori i nomi delle variabili e dei sottoprogrammi. • Le parole chiave sono parole che hanno un preciso significato e sono riservate: non devono essere usate come nomi di identificatori. Ad esempio: • Nella costruzione dei nomi degli identificatori e delle parole chiave si fa distinzione tra maiuscole e minuscole: le parole chiave sono riservate se scritte in minuscolo. • Si utilizzano caratteri alfabetici e numerici, _,$ • Non si devono inserire spazi: lo spazio è un separatore. • Ogni nome di identificatore inizia con una lettera alfabetica. • int, if, main, … • int: nome di tipo di dato intero • if: nome della struttura di scelta • main: nome del programma principale • Esempi: alfa Alfa (par. 13.2) A lfa (no) 2area(no) area2 Struttura di un programma La struttura di un programma • Un programma nel linguaggio C++ è composto da uno o più moduli, ciascuno dei quali può contenere una o più funzioni e delle istruzioni chiamate “direttive” per il preprocessore, introdotte dal simbolo #. • Uno ed uno solo di questi moduli contiene la funzione main. • Il main è il “programma principale”: viene attivato direttamente dal Sistema Operativo. (par. 13.3) 36 Struttura di un programma • Esempio di programma costituito da tre moduli #include … int main() … ….istruzioni //chiama funz1 //intestazione funz1 //intestazione funz2 ….istruzioni ….istruzioni //chiama funz2 //fine funz1 //fine main primo.c secondo.c //fine funz2 terzo.c Analisi di un semplice programma #include <iostream> using namespace std; int main () {/*programma che invia all'uscita standard un messaggio */ cout<<"ciao a tutti"<<endl; return 0; } • Occorre fare molta attenzione: il testo va inserito esattamente come è presentato. • Il programma invia all’uscita standard il messaggio rappresentato da “ciao a tutti”. Analisi di un semplice programma • Tradizionalmente, il primo programma che si scrive quando si impara un linguaggio di programmazione ha il compito di visualizzare sullo schermo un semplice saluto. • Utilizzando un editor di testi, costruiamo un file di nome ciao.c oppure ciao.cpp • il nome del file serve per ricordare il significato del programma; l’estensione c oppure cpp indica il tipo di contenuto (si tratta di righe di testo scritte nel linguaggio C o C++) ed è obbligatoria. Analisi di un semplice programma • compiliamo il programma g++ -o ciao ciao.c • il compilatore genera un file eseguibile (senza estensione) • eseguiamo il programma ./ciao • otteniamo la visualizzazione del messaggio ciao a tutti 37 Analisi di un semplice programma Analisi di un semplice programma • L’istruzione include serve per inserire il file di intestazione (header file) di nome iostream che contiene le definizioni e le istruzioni per gestire le operazioni di ingresso/uscita. • A seconda del sistema operativo usato (o della versione del compilatore) si possono avere altri nomi per i file da inserire: • L’istruzione include deve essere scritta preceduta dal simbolo # posto in prima colonna. • Il file viene inserito nel punto in cui è scritta l’istruzione. • Se non sono presenti istruzioni di ingresso o uscita tale istruzione non è necessaria (ad esempio nel modulo di nome secondo.c potrebbe non esserci alcuna istruzione di lettura/scrittura). • iostream.h • stdio.h • conio.h oppure iostream.hpp Analisi di un semplice programma Analisi di un semplice programma • L’istruzione using namespace std; indica una nuova versione dello standard per I/O. • I commenti sono istruzioni che non vengono eseguite, ma servono ad introdurre frasi di spiegazione e possono essere introdotti in due diversi modi: • Parentesi. • Abbiamo parentesi tonde, quadre e graffe con diversi significati. • La coppia di parentesi graffe { } delimita le istruzioni relative ad un blocco di istruzioni: nell’esempio le istruzioni del programma main. // il commento occupa una sola riga /* commento scritto su più righe */ • È bene inserire dei commenti che indichino cosa fa il programma o un gruppo di istruzioni e quale è il significato delle variabili. 38 Analisi di un semplice programma Analisi di un semplice programma • Le unità di programma sono funzioni. • In tutti i linguaggi di programmazione le funzioni hanno un nome, possono avere 0, 1 o più parametri, argomenti, di ingresso ed hanno sempre un valore di ritorno. • Gli argomenti sono scritti tra parentesi rotonde e, se più di uno, sono separati da virgola. • Ogni funzione che restituisce un valore deve avere una esplicita istruzione di ritorno del tipo: return espressione; • dove espressione può essere una costante, una variabile o una espressione (il cui valore viene calcolato prima di essere restituito). • Per il main si scrive: return 0; • Il valore 0 rappresenta un codice di ritorno al S.O. che indica che l’esecuzione è andata a buon fine (senza errori). • Per convenzione il main è di tipo intero: int main() Analisi di un semplice programma • Ogni istruzione termina con un ; • Ogni linguaggio gestisce una uscita standard (vedremo poi altri tipi di uscite). Nel C++ l’uscita standard è rappresentata dal nome cout • Per poter inviare l’informazione al file standard cout si utilizza l’operatore << (operatore di uscita). Analisi di un semplice programma • Se non viene esplicitamente indicato, non si va mai a capo: pertanto per non costruire righe troppo “larghe” si dovrà indicare che la riga è finita e se ne inizia un’altra. • La fine della riga viene indicata con endl (end line) • Per aggiungere al flusso di informazioni in uscita la parola endl si concatena l’operatore di uscita all’informazione precedente: cout<<"ciao a tutti"<<endl; 39 Analisi di un semplice programma • Ciò che si vuole trasmettere in uscita è un messaggio, cioè una stringa di caratteri. • Le costanti stringa vengono scritte tra virgolette: "ciao a tutti " • Le virgolette non fanno parte della stringa. 40