UD 3.2d: Linguaggi di programmazione Bibliografia Curtin (vecchie edizioni): 12.2 Curtin (IV edizione): 11.2 Questi lucidi Ma che cos’è un programma? E’ un insieme di istruzioni E’ una procedura o meglio un algoritmo che viene eseguito dalla macchina le permette di portare a termine le operazioni che le abbiamo richiesto Il programma per essere comprensibile deve dare istruzioni o fare dichiarazioni usando un linguaggio che la macchina possa capire I linguaggi di programmazione Possono essere più vicini al modo di pensare del programmatore o a “quello” della macchina Sono scritti in una lingua coerente e priva di ambiguità Comprenderne i principi è semplice, ma diventare un bravo programmatore lo è meno Maggiore è la distanza del linguaggio dal linguaggio macchina e la vicinanza al linguaggio naturale, più “alto” sarà il “livello” del linguaggio I “livelli” dei linguaggi Linguaggi ad altissimo livello (dichiarativi): si dice al computer cosa si vuole senza specificare come deve fare per operare (es.: SQL, Lisp, Prolog, ecc.) Linguaggi ad alto livello: più vicini al nostro modo di comprendere e impostare problemi, più facili da imparare e da trasferire e da ‘portare’ su un altro computer (es.: Pascal, Java, C++, Visualbasic, ecc.) Linguaggi a basso livello: vicini al linguaggio macchina e all’architettura fisica del computer (es.: Assembler) Linguaggio macchina: usa solo 0 e 1 ed è comprensibile direttamente dall’hardware, ma molto difficile per l’uomo I “livelli” dei linguaggi I “livelli” dei linguaggi Linguaggio macchina stringhe di bit corrispondenti ad istruzioni, operandi, etichette ed indirizzi di memoria. Strettamente legato alla macchina. Persone in grado di manipolare simboli (parole) più che sequenze di cifre Linguaggio assembler Rappresentazione simbolica del linguaggio macchina, più comprensibile perché usa simboli invece di bit. Linguaggi di alto livello Linguaggio simile a quello naturale, il programmatore si astrae dai dettagli della macchina. I “livelli” dei linguaggi int main(int argc, char *argv[]) { int i; int sum=0; for (i=0; i <= 100; i++) sum = sum + i; printf(“The sum from 0 .. 100 is %d\n”, sum); } Procedurale vs. Dichiarativo Linguaggi procedurali: Forniscono al computer una serie di ordini su cosa debba fare e in quale circostanza. L’aspetto della descrizione del problema, quando esiste è minimizzato: il computer “non sa” niente Procedurali: Cobol, Fortran, Pascal, Basic, C Linguaggi dichiarativi: Descrive, dichiara quali sono i dati del problema, fornisce le regole che si possono seguire e lascia che sia il computer a decidere come agire. Possono essere più faticosi per il computer perché deve derivare da solo le procedure da adottare I linguaggi a basso livello L’Insieme delle Istruzioni del Processore Ogni processore è in grado di eseguire solo poche istruzioni elementari quali: Somma di due numeri (già la somma di tre numeri viene effettuata tramite due somme elementari) Confronto tra due numeri con individuazione del fatto che ci sia o meno differenza (non tutti i processori sanno distinguere in modo immediato, invece, quale dei due precede l’altro) Spostamento dei bit all’interno di una parola di qualche posizione a destra o a sinistra. poche altre ancora … Linguaggio Macchina Per gestire hardware bisogna parlare il linguaggio del calcolatore Linguaggio perché presenta Parole (cioè le istruzioni) Sintassi (regole di combinazione delle parole per generare frasi corrette) Sintassi di un linguaggio di programmazione Molto semplice (poche regole) Molto rigorosa (per evitare ogni tipo di ambiguità) Istruzioni in Linguaggio Macchina Istruzione in LM è una successione di 32 bits rappresentabile da un numero La funzione di questo numero è di codifica (rappresentazione di informazioni), non è un numero vero e proprio Ogni istruzione è scomponibile in frammenti più piccoli, ognuno dei quali rappresenta un tipo di informazione (codice operativo, una costante, il numero di un registro). Istruzioni in Linguaggio Macchina Le istruzioni si distinguono per il valore contenuto nel primo campo In base ad opcode l’hardware sa come trattare il resto dell’istruzione Istruzioni in Linguaggio Macchina L’istruzione che somma due numeri che sono stati già trasferiti dalla RAM nei registri numero 17 e 18 e memorizza il risultato nel registro numero 8 è rappresentabile come segue: 00000010001100100100000000100000 000000 6 bits 10001 5 bits 10010 5 bits 01000 5 bits 00000 5 bits 100000 6 bits 0 17 18 8 0 32 In decimale: Linguaggi macchina: problemi Sono specifici della macchina Occorre conoscere l’architettura della macchina per scrivere programmi I programmi non sono trasportabili I programmatori si specializzano nel cercare efficienza su una macchina specifica, anziché concentrarsi sul problema Istruzioni e operandi sono rappresentati in forma numerica I codici sono poco leggibili e quindi difficilmente modificabili I programmi sono facilmente soggetti ad errori sw $16, 0($2) sw $15, 4($2) jr $31 Linguaggio Macchina Assembler Il Linguaggio Macchina non è facilmente “utilizzabile” Binary machine language program (for MIPS) 00000000101000010000000000011000 00000000100011100001100000100001 10001100011000100000000000000000 10001100111100100000000000000100 10101100111100100000000000000000 10101100011000100000000000000100 00000011111000000000000000001000 Un programmatore utilizza una versione più “ad alto livello” del LM: il linguaggio Assembler Linguaggio Assembler Linguaggio simbolico che utilizza simboli invece che bits. I simboli associano nomi ai codici operativi o i riferimenti ai registri. Permette di utilizzare etichette invece che indirizzi fisici Le istruzioni in Assembler sono quasi tutte in corrispondenza 1<->1 con quelle in linguaggio macchina Programma in Linguaggio Macchina Calcolo e stampa della somma dei numeri compresi tra 1 e 100. Programma in LM Programma in Linguaggio Assembly Una prima rappresentazione simbolica del programma in LM visto in precedenza è la seguente Operazioni e operandi sono rappresentati in maniera simbolica. Assemblatore Uno strumento che traduce programmi scritti nel linguaggio assembler in linguaggio macchina. L’assembler legge un file sorgente in assembler produce un file oggetto contenente insieme di istruzioni in LM, di dati e di informazioni necessarie per il caricamento in memoria delle istruzioni UD 3.2f: Linguaggi ad alto livello Programma in Linguaggio al alto livello Il formato precedente è ancora difficile da seguire perché: Usa molte piccole operazioni per eseguire compiti semplici I costrutti per il controllo del flusso sono realizzati con confronti e salti (più difficili da leggere) Programma in Linguaggio al alto livello Linguaggio “C”: #include <stdio.h> int Linguaggio “Pascal”: main (int argc, char *argv[]) { int i; int sum = 0; for (i = 0; i <= 100; i = i + 1) sum = sum + i; printf ("The sum from 0 .. 100 is %d\n", sum); } Program somma; Var i, somma : integer; Begin somma := 0; for i:=1 to 100 do somma := somma + i; write (‘La somma dei primi 100 numeri vale: ‘, somma); End. Esempio 2 PASCAL: x := h + x ASSEMBLER(*) : lw 8, 1200 add 8, 18, 8 sw 8, 1200 100011 000000 101011 01001 10010 01001 01000 01000 01000 0000 0100 1011 0000 01000 00000 010000 0000 0100 1011 0000 LINGUAGGIO MACCHINA(*) (binario): 10001101001010000000010010110000 00000010010010000100000000010000 10101101001010000000010010110000 (*) Si suppone che il registro 8 contiene x e che il registro 18 contiene h Linguaggi di Programmazione ad alto livello Notazione vicina al linguaggio naturale (facile comprensibilità) Permette di incrementare la produttività, facilitando il compito di scrittura dei programmi ai programmatori Uso di librerie già scritte (riuso del codice) Un programma scritto in HLL (High Level Language, cioè Linguaggio ad Alto Livello) è (quasi sempre) indipendente dalla architettura (processore) su cui il programma va eseguito. Linguaggi di Programmazione ad alto livello Traduzione dei linguaggi Il programmatore utilizza un linguaggio ad alto livello senza preoccuparsi della macchina che esegue il programma Un Linguaggio di Programmazione ad alto livello non è direttamente “comprensibile” al computer. Deve quindi esistere un meccanismo che “traduca” un programma dal formato “linguaggio ad alto livello” al formato “linguaggio macchina” Compilatore Il Compilatore è un software che traduce un programma scritto in un linguaggio ad alto livello (detto programma sorgente) in un programma equivalente in linguaggio macchina (detto programma oggetto) Quasi sempre tale traduzione avviene in due fasi, passando attraverso un linguaggio intermedio, l’assembler Un compilatore produce quindi un programma eseguibile (.exe in Windows) Compilatore Il compilatore viene predisposto per una macchina specifica e poi traduce tutti i programmi scritti in uno specifico linguaggio ad alto livello Il concetto di traduzione dei linguaggi ha permesso l’evoluzione verso sistemi simbolici più espressivi e più facilmente manipolabili dai programmatori Compilatore e Assemblatore Programma in linguaggio ad Alto Livello High-level language program (in C) COMPILATORE C compiler Assembly language program (for MIPS) Programma in linguaggio Assembler ASSEMBLATORE swap: muli $2, $5,4 add $2, $4,$2 lw $15, 0($2) lw $16, 4($2) sw $16, 0($2) sw $15, 4($2) jr $31 Assembler Binary machine language program (for MIPS) Programma in linguaggio Macchina swap(int v[], int k) {int temp; temp = v[k]; v[k] = v[k+1]; v[k+1] = temp; } 00000000101000010000000000011000 00000000100011100001100000100001 10001100011000100000000000000000 10001100111100100000000000000100 10101100111100100000000000000000 10101100011000100000000000000100 00000011111000000000000000001000