TRADUZIONE DEL PROGRAMMA Una volta che un programma sia stato scritto in C, esso non può essere eseguito senza unulteriore traduzione. Ciò perché qualsiasi.

Slides:



Advertisements
Presentazioni simili
Linguaggio C e C++.
Advertisements

Ing. Pasquale Zambrotta
Introduzione al linguaggio C++
I Linguaggi di programmazione
Traduzione ed Interpretazione
Il Software.
Dalla scrittura all’esecuzione
Evoluzione dei linguaggi di programmazione
I linguaggi di programmazione
Sintassi (prima parte)
Type Checking (1° parte)
Generazione di Codice Intermedio
Algoritmi e Programmazione
Generalità Linguaggio e Macchina Astratta
Dr. Francesco Fabozzi Corso di Informatica
Anno accademico Il preprocessore del linguaggio C.
Interfaccia del file system
Fondamenti di Informatica I a.a Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.
Programmazione Procedurale in Linguaggio C++
Indirizzi delle variabili A ogni variabile sono associati tre concetti fondamentali: il valore memorizzato; il tipo dati di appartenenza; lindirizzo. Il.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Caratteri e stringhe di caratteri
Argomenti dalla linea dei comandi Gli argomenti possono essere passati a qualsiasi funzione di un programma, compresa la main(), direttamente dalla linea.
Iterazione enumerativa (for)
Funzioni definite dall’utente
Informatica di base A.A. 2003/2004 Algoritmi e programmi
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Introduzione a JAVA Anno Accademico 2009/2010.
Corso di Laurea in Biotecnologie Informatica (Programmazione)
Corso di Informatica (Programmazione)
Programmazione Un programma descrive al computer, in estremo dettaglio, la sequenza di passi necessari a svolgere un particolare compito L’attività di.
Introduzione alla programmazione lll
Struttura dei sistemi operativi (panoramica)
1 Generazione codice Daniela Briola Lorena Bellino.
Unità Didattica 2 I Linguaggi di Programmazione
Il sistema operativo Vito Perrone
Fondamenti di Informatica1 Software di base Tra il linguaggio macchina (basso livello) e i linguaggi evoluti (alto livello) esiste uno strato di software.
SOFTWARE I componenti fisici del calcolatore (unità centrale e periferiche) costituiscono il cosiddetto Hardware (alla lettera, ferramenta). La struttura.
Espressioni condizionali
INSIEMI NUMERABILI L’analisi matematica introduce il concetto di insieme numerabile come insieme i cui elementi possono essere “contati” ossia che possiede.
Corso di PHP.
Fondamenti di informatica Linguaggio C Main Program: Architettura di un PC Diagrammi di flusso Linguaggio C.
PROGRAMMAZIONE: linguaggi
Introduzione al linguaggio assembly del microprocessore a parte
Introduzione al linguaggio assemby del microprocessore a parte
Lezione 1 Linguaggi di programmazione – Algoritmi –Istruzioni
CODIFICA Da flow-chart a C++.
Lo sviluppo del software e i linguaggi di programmazione
Unità Didattica 3 Linguaggio C
Lezione 3 Struttura lessicale del linguaggio
Elettronica Digitale (II Parte) 10-11_5 1 ELETTRONICA DIGITALE II (5) 6/12 Il processo di assemblaggio.
Introduzione a Javascript
INTERFACCE Schede elettroniche che permettono al calcolatore di comunicare con le periferiche, che possono essere progettate e costruite in modo molto.
Vettori (a una dimensione)
Informatica Lezione 5 Scienze e tecniche psicologiche dello sviluppo e dell'educazione (laurea triennale) Anno accademico:
Introduzione Laboratorio di Calcolo Corso di Laurea in Fisica Università degli Studi di Roma “La Sapienza”
Scrivere e compilare programmi
Programmazione Attività di progettazione ed implementazione di programmi I programmi permettono di realizzare funzioni complesse su un hardware in grado.
L’esecuzione dei programmi
Concetti Fondamentali sulla Programmazione
1 Macchine astratte, linguaggi, interpretazione, compilazione.
Progettazione di basi di dati: metodologie e modelli
Il software Claudia Raibulet
Esercizi.
Informatica e Informatica di Base
Problemi, algoritmi e programmazione
“ Pseudocodice ” Un programma per computer lavorerà su in insieme di “ variabili ” contenenti i dati del problema, soluzioni intermedie, soluzioni finali.
Informatica Problemi e algoritmi. una situazione che pone delle domande cui si devono dare risposte. Col termine problema o situazione problematica s’indica.
Parsing ricorsivo discendente Il parsing ricorsivo discendente (recursive descent parsing) è un metodo di tipo top-down che può essere facilmente codificato.
Unità di apprendimento 6
ALGORITMI, LINGUAGGI E PROGRAMMI Facoltà di Lingue e Letterature Straniere Corso di laurea in Relazioni Pubbliche.
Transcript della presentazione:

TRADUZIONE DEL PROGRAMMA Una volta che un programma sia stato scritto in C, esso non può essere eseguito senza unulteriore traduzione. Ciò perché qualsiasi computer è in grado di eseguire solo le istruzioni scritte nel linguaggio proprio della sua architettura, detto linguaggio macchina, costituito da una serie di 0 e 1. Dato che la programmazione in linguaggio macchina è difficile e soggetta a errori, sono stati sviluppati dei programmi, detti genericamente traduttori, che accettano in ingresso un programma scritto in un linguaggio di alto livello (per esempio in C), detto programma sorgente, e producono in uscita un programma scritto in linguaggio macchina, detto programma (o codice) oggetto.

Un programma può essere tradotto in linguaggio macchina secondo due strategie diverse, ossia usando un programma interprete oppure un programma compilatore: un programma interprete traduce individualmente ogni istruzione del programma sorgente e la esegue immediatamente; quindi non produce un codice oggetto. un programma compilatore traduce tutte le istruzioni del programma sorgente in un programma equivalente, prima che ciascuna di esse sia eseguita; quindi produce un codice oggetto. Il C è un linguaggio compilato, quindi il programma sorgente è tradotto come un tuttuno nel linguaggio macchina. In realtà, la traduzione di un programma sorgente in un programma eseguibile avviene in due passaggi consecutivi: il primo eseguito da un programma detto compilatore il secondo eseguito da un programma detto loader/linker.

Il compilatore dunque accetta in ingresso il programma sorgente e produce in uscita un programma oggetto, scritto nelle istruzioni proprie del microprocessore usato (ossia in linguaggio assembly). In genere il programma oggetto non consiste in un codice adatto per lesecuzione, codice che sarà prodotto successivamente da un gruppo di tre programmi datti assemblatore, legatore, caricatore.

Intel 4004 Instruction Set

Programma compilatore. Un compilatore è costituito in realtà da diversi programmi, che eseguono sul sorgente un certo numero di operazioni. Esse si possono dividere in due parti: analisi e sintesi. Lanalisi suddivide il programma sorgente nelle sue parti costituenti e ne crea una rappresentazione intermedia. La sintesi genera il programma target dalla rappresentazione intermedia. La parte di analisi si può suddividere nelle seguenti fasi: 1. analisi lessicale (o lexing); 2. analisi sintattica (o parsing); 3. analisi semantica; La parte di sintesi si può suddividere nelle seguenti fasi: 1. generazione del codice intermedio; 2. ottimizzazione del codice; 3. generazione del codice finale.

Alla fine viene prodotto il programma target.

Lanalisi lessicale può rilevare errori relativi alla grafia delle parole chiave o di identificatori creati dallutente, al formato delle costanti,... Ad es., il seguente diagramma lessicale permette di stabilire se un identificatore abbia il formato corretto (cioè inizi con una lettera, seguita da lettere e/o cifre). Nellanalisi lessicale (o lexing) il programma è considerato come ununica sequenza di caratteri; essa viene scansionata per individuare gli elementi base del linguaggio che costituiscono unistruzione, quali parole chiave, identificatori, costanti, operatori, delimitatori,... Un analizzatore lessicale legge il programma da sinistra a destra e raggruppa le sequenze di caratteri in token, che sono unità lessicali di significato compiuto. La sequenza di caratteri che dà luogo a un token è detta lessema.

Una volta eseguita lanalisi lessicale, le fasi successive della compilazione non faranno più riferimento ai singoli caratteri, ma alle parole individuate come elementi di base.

Consideriamo, come esempio, la seguente istruzione di assegnazione: totale = base + increm * 60 Lanalizzatore lessicale raggruppa i caratteri nei seguenti token: A questo punto il compilatore costruisce una Tabella dei simboli, dove registra gli identificatori usati nel programma insieme ai loro attributi. Essa ha laspetto indicato in figura

Come si vede, gli attributi di un token ID si possono riferire a: memoria allocata, tipo dati, portata o ambito, numero e tipo di argomenti, ecc. Quando viene rilevato un identificatore e generato un token ID, il lessema corrispondente è inserito nella Tabella dei simboli, e al token ID viene associato un puntatore alla posizione nella Tabella. Si ottengono anche una o più tabelle dei simboli contenenti tutti gli identificatori dichiarati nellambito del programma come tipi, variabili, procedure, funzioni,... che saranno utilizzate nelle successive fasi di analisi semantica, generazione del codice e gestione della memoria.

Nellanalisi sintattica, o parsing, viene riconosciuta la struttura del programma e viene rappresentato il suo significato in una forma intermedia, dalla quale verrà poi prodotto con semplici trasformazioni il codice oggetto. Lanalisi sintattica è guidata dalla definizione formale del linguaggio di programmazione - data per esempio mediante la forma normale di Backus o i diagrammi sintattici - e consente di caratterizzare tutti e soli i programmi validi, cioè sintatticamente corretti, e di comprenderne il significato. Ad es., il seguente diagramma sintattico permettere di stabilire se sia stato impiegato un identificatore valido in C

Il diagramma seguente permette invece di controllare la validità di una istruzione if.

I token vengono raggruppati in frasi grammaticali rappresentate da un albero parse, che fornisce una struttura gerarchica al programma sorgente. La struttura gerarchica è espressa da regole ricorsive dette produzioni. Gli errori che si rilevano in questa fase riguardano lerronea strutturazione del programma a partire dalle proposizioni, ad es. la mancata corrispondenza di parametri in unespressione, lassenza di parole chiave attese in determinate posizioni (come il while dopo il do), la mancanza della parola chiave case in corrispondenza di una switch e così via. Come risultato di questa fase si ottiene una forma intermedia (albero, matrice,...) corrispondente alla struttura sintattica del programma analizzato.

Ecco un esempio di albero parse ID = ID | NUM | | ( ) + | - | *| / Ad es., produzioni per istruzioni di asegnazione sono:

Nellanalisi semantica vengono compiute diverse verifiche di consistenza semantica dei concetti utilizzati dal programma. Ad esempio, la frase il libro legge lo studente è sintatticamente corretta, mentre risulta errata dal punto di vista del significato. Lanalisi semantica di un programma verifica: se gli identificatori usati in una procedura siano stati dichiarati nella procedura stessa, se rispettino le regole di visibilità previste dal linguaggio per variabili e procedure, e se il loro tipo sia coerente con luso che ne viene fatto (ad es., i numeri reali non possono essere usati come indici dei vettori). In caso di errori viene fornita la diagnostica relativa.

Fase di sintesi A partire dalla forma intermedia acquisita durante lanalisi sintattica avviene la generazione del codice intermedio, nella forma di un programma per una macchina astratta. Il codice deve essere facilmente traducibile nel programma target. Tale generazione avviene in base a regole molto semplici, che fanno corrispondere unistruzione macchina a ciascuna struttura elementare rappresentata nella forma intermedia.

Questi interventi possono essere: dipendenti dalla macchina, se tengono conto delle caratteristiche hardware e del repertorio di istruzioni del computer su cui dovrà operare il codice oggetto; indipendenti dalla macchina, se non ne tengono conto. I diversi compilatori adottano diverse tecniche di ottimizzazione. Il codice prodotto nella fase precedente può non essere efficiente. Al fine di ottenere un programma oggetto corto ed efficiente si possono effettuare vari interventi di ottimizzazione del codice. Per esempio spostare allesterno di un ciclo le istruzioni che non dipendono dalle variabili del ciclo stesso, eliminare il calcolo di espressioni ripetute più volte o semplificare espressioni aritmetiche o logiche.

Nella generazione del codice viene prodotto il codice target in linguaggio assembly, una versione mnemonica del codice macchina che usa: codici operativi o mnemoniche per le operazioni (Tabella dei codici); nomi simbolici per gli operandi (al posto delle locazioni di memoria) (Tabelle dei simboli); Vengono scelte le locazioni di memoria per ciascuna variabile, le istruzioni sono tradotte in una sequenza di istruzioni assembly e le variabili e i risultati intermedi sono assegnati ai registri di memoria.

Programmi assemblatore, legatore, caricatore. Il programma assemblatore (assembler) sincarica di tradurre ciascuna istruzione del codice target in una in linguaggio macchina, producendo un codice in linguaggio macchina secondo lo schema seguente Tuttavia, mentre la traduzione del codice operativo in linguaggio macchina è in ogni caso univoca, non è sempre possibile sostituire immediatamente a ogni riferimento simbolico di locazione di memoria lindirizzo effettivo della relativa locazione.

Infatti gli operandi che indicano una locazione di memoria possono indicare: indirizzi assoluti, quali quelli dei dispositivi di ingresso/uscita, che non dipendono ovviamente dalla particolare collocazione del programma in memoria. Essi possono essere tradotti direttamente in indirizzi binari; indirizzi relativi ai dati e alle istruzioni del codice macchina. Ovviamente tali indirizzi cominciano da 0, e affinché il codice possa esere eseguito correttamente, essi dovrebbero rimanere gli stessi anche quando il codice viene caricato in memoria centrale. Ciò richiederebbe che il codice venisse allocato in memoria a partire dallindirizzo 0, cosa non sempre possibile; daltra parte, la grande maggioranza dei codici possono essere caricati in qualsiasi zona di memoria disponibile (per cui sono detti codici rilocabili). Gli indirizzi relativi, che a differenza di quelli assoluti devono essere tradotti in indirizzi di memoria centrale tenendo conto dellindirizzo di memoria a partire dal quale il programma viene caricato, sono detti anche rilocabili.

Per gli operandi rilocabili lassemblatore crea, in una prima fase, una tabella dei simboli, nella quale pone i nomi che individua come riferimenti simbolici e la loro posizione relativa nel programma. Solo in una seconda fase gli operandi simbolici saranno sostituiti con gli indirizzi corrispondenti, consultando la tabella dei simboli. Perciò il programma assemblatore viene detto a due passi o fasi.

Programma legatore. Prima della trasformazione definitiva di tutti gli indirizzi in assoluti, è però necessaria unaltra operazione, eseguita dal programma legatore (linker). Esso unisce insieme i differenti file e moduli che possono costituire un sigolo programma (file oggetto), ai quali aggiunge eventualmente dei file di biblioteca (library). Spesso i termini linker e loader sono usati in modo interscambiabile.

Programma caricatore. A questo punto interviene il programma caricatore (loader), per trasformare tutti gli indirizzi in assoluti. Esso memorizza in uno speciale registro base o di riferimento lindirizzo di memoria a partire dal quale viene caricato il programma (detto indirizzo base), quindi somma tale indirizzo base a ogni indirizzo relativo, ottenendo un indirizzo assoluto.

In tal modo, se sarà necessario spostare il programma in unaltra zona di memoria (processo detto rilocazione), sarà sufficiente modificare il valore dellindirizzo base. Riassumendo, la trasformazione degli operandi di un programma in linguaggio assembly avviene, nel caso più generale, nelle tre fasi seguenti:

lassemblatore trasforma gli operandi simbolici in indirizzi assoluti, rilocabili o globali il legatore trasforma gli indirizzi globali in rilocabili il caricatore trasforma gli indirizzi rilocabili in assoluti.

Compilatore DMC. In Internet si trovano ottimi compilatori assolutamente freeware. Noi utilizzeremo il compilatore DMC della Digital Mars, che si può scaricare gratuitamente allindirizzo cliccando sul link:

Si tratta di un programma che esegue la complazione e il link di file C, C++ e ASM in un solo passaggio. Il download crea nella cartella Documenti una cartella dm con alcune sottocartelle:

Dato che il compilatore ( dmc.exe ) si trova nella sottocartella bin, il modo più veloce (anche se non il più elegante) per provare il funzionamento dei propri programmi in C consiste nel: 1.salvare il proprio programma in formato solo testo e con estensione.c nella sottocartella bin della cartella dm ; 2.eseguire il programma Prompt dei comandi da Start Tutti i programmi Accessori 3. dal prompt C:\Documents … \Documenti> digitare: cd dm\bin dmc hello.c 4. se loperazione ha successo, vengono creati i tre file hello.exe, hello.map, hello.obj, il primo dei quali si può ora eseguire con il comando hello