Come impostare un programma? - e-Learning

Transcript

Come impostare un programma? - e-Learning
Università degli Studi di Milano-­‐Bicocca Scuola di Scienze Dipartimento di Informatica, Sistemistica e Comunicazione Viale Sarca, 336 – 20144 Milano – www.disco.unimib.it Consiglio di Coordinamento Didattico di Scienze e Tecnologie Informatiche Come impostare un programma? F. Tisato 13/1/2014 Parlando con qualcuno di voi ho verificato che potete incontrare qualche difficoltà nell’impostazione di un programma Asm. Suggerimento fondamentale: non cercate di “progettare” il programma direttamente in Asm. Rischiereste di confondere gli aspetti concettuali (la logica del’algoritmo da eseguire) con tutti i dettagli pratici che derivano dalla programmazione Asm. Dovete: •
•
prima esaminare il problema definendo le variabili che servono e gli aspetti algoritmici, usando costrutti astratti (come quelli che usereste in un linguaggio di alto livello) poi tradurre i singoli pezzetti in Asm, utilizzando per quanto possibile schemi standard (ricavabili dal testo, degli esempi...e da un po’ di esperienza). In sostanza: prima progettare occupandosi della logica, non dell’implementazione; poi tradurre i pezzetti, comportandosi come un compilatore, che traduce in Asm un pezzetto per volta, senza preoccuparsi di “cosa fa” il programma nel suo complesso. Esempio Problema (senza uso di procedure): scrivere un programma che, dato un vettore chiamato “vett” di 5 elementi che contengono interi, trova il massimo e lo scrive in una variabile “max”. Impostazione del problema Non uso volutamente uno specifico linguaggio di programmazione di alto livello, ma uno pseudolinguaggio che è un misto di linguaggio naturale e linguaggio di programmazione. Ciò per evitare dettagli e per evidenziare che qui si tratta di esprimere la logica complessiva, non è un programma effettivo scritto in uno specifico linguaggio di programmazione. Serve a noi per ragionare senza occuparsi dei dettagli programmativi. Di seguito i passi fondamentali: Quali variabili mi servono? Devo dichiarare (cioè riservare spazio nella memoria dati) per: 1. un array di 5 interi, che decido di chiamare vett 2. un intero per il risultato, che decido di chiamare max Poi mi potrà servire qualche variabile di servizio (contatori eccetera), vedremo strada facendo. CCD di Scienze e Tecnologie Informatiche Cosa fa l’algoritmo? In “pseudocodice”, qualcosa come 3. cont := 0 4. i := 0 5. max := vett[0] (commento): cont è una variabile “di servizio” di tipo intero che serve per contare il numero di esecuzoni del ciclo. i è la variabile (“indice”) che definisce l’elemento del vettore cui accedere. Sì, lo so, apparentemente ne basta una perché in questo esempio le due variabili sembrano avere sempre lo stesso valore...ma non vuol dire che siano la stessa variabile, come vedremo dopo. 6. do { 7. cont++ 8. i++ 9. if (vett[i] > max) then 10. max:= vett[i]} 11. while (cont < 4) Spero sia chiaro. Suggerimento: una volta definita la logica, provate a implementarla (ad esempio in Java, qui non lo faccio), e poi (partendo ancora dalla logica) proviamo a implementarla in Asm. Che è quello che segue. Come dichiaro le variabili (righe 1. e 2.), in modo che sia allocata memoria in corrispondenza dei nomi simbolici (etichette)? NB: per comodità, faccio direttamente l’inizializzazione del vettore. In un programma reale, dovrei probabilmente leggere i valori in input tramite una Syscall. Oppure scrivere una procedura (vedere esempio 3_sommavett1.2.asm, o altri esempi). Per il momento, lasciamo perdere. .data vett: .word 1, 4, 2, 55, 13 # il vettore inizializzato max: .word 0 # il massimo inizializzato Mi servirà anche il contatore del ciclo cont. Dato che è una variabile usata solo localmente nell’algoritmo e non mi viene richiesto di memorizzarla, decido di usare il registro temporaneo $t0. Per quanto riguarda i...ne parliamo dopo. Per fare una cosa un po’ più efficiente, decido di tenere i valori temporanei del massimo (calcolati a ogni ciclo) nel registro $t1, e di memorizzare il risultato finale in max alla fine del programma. Come realizzo i pezzetti dell’algoritmo? ATTENZIONE: lo faccio in modo molto meccanico un pezzetto per volta, senza preoccuparmi di cosa fa l’algoritmo nel suo complesso! Il modo di tradurre i singoli pezzetti non cambia nella sostanza nel caso di un algoritmo molto più complicato. Mi comporto come un compilatore, che “non sa” cosa fa l’algoritmo. Di seguito uso i numeri di linea dello “pseudo-­‐programma” sopra. Devo dire che qui comincia il codice eseguibile .text .globl main main: 3. cont := 0 può essere implementato come 2 CCD di Scienze e Tecnologie Informatiche move $t0, $zero Nel seguito dovrò far riferimento agli elementi del vettore. Per poterlo fare, inizializzo nel registro $t2 l’indirizzo del primo elemento del vettore, che corrisponde all’etichetta vett. Ciò corrisponde logicamente a 4. i := 0 che può quindi essere implementato come la $t2, vett NB: questa è una tecnica generale che serve per accedere agli elementi di un vettore (vedere esempi) Quindi 5. max := vett[0] può essere implementato come lw $t1, 0($t2) Adesso c’è un ciclo. 6. definisce l’inizio del loop, quindi mi serve una etichetta (NB: potrei chiamarla in qualsiasi modo) loop: 7. cont++ può essere implementato come addi $t0, $t0, 1 8. i++ serve per puntare al prossimo elemento del vettore. Ricordando che $t2 viene usato per pntare all’elemento corrente (vedi 4.) e che un elemento (word) è di 4 byte, per puntare al prossimo elemento si fa addi $t2, $t2, 4 Adesso c’è un if (9.). Qui occorre qualche giochetto (si può fare in diversi modi; questo è solo un possibile esempio). Per prima cosa, bisogna valutare l’espressione logica; cosa che richiede di avere gli operandi in registri. max è già in $t1. Usiamo $t3 per recuperare vett[i]: lw $t3, 0($t2) Poi valutiamo (vett[i] > max). In base all’algoritmo (9.), se la condizione è verificata, va eseguita la 10. In Asm può essere opportuno ribaltare: se la condizione NON è verificata, NON si fa quello che segue saltando a una etichetta (“endif” – che, come al solito. è un nome simbolico arbitrario). Perciò, valutiamo (max < vett[i]) mettendo il risultato in $t4 slt $t4, $t1, $t3 e, se la condizione non è verificata ($t4 = 0), saltiamo a endif (che definiremo dopo) beq $t4, $zero, endif Poi facciamo quello che va fatto se la condizione è verificata (10. max:= vett[i]) move $t1, $t3 A questo punto c’è quello che va fatto comunque endif: cioè 11. while (cont < 4) cioè, se (cont < 4) si salta all’inizio del loop 3 CCD di Scienze e Tecnologie Informatiche blt $t0, 4, loop Quando si esce dal loop, rimane solo da salvare il risultato nella variabile max sw $t1, max e terminare il programma lw $a0, 10 syscall In Programma1.asm trovate il programma (scritto prendendo una per una le istruzoni asm sopra). COMMENTO FINALE (per ribadire quanto scritto all’inizio): anche in un caso molto semplice come questo, progettare direttamente il programma “ragionando in Asm” è cosa da hacker, ed è comnque concettualmene sbagliato. Prima si deve analizzare il problema (“problem solving”) e disegnare nel suo complesso la soluzione (“pseudocodice”, o uso di diagrammi di flusso e quant’altro; senza perdersi in dettagli implementativi. Questo vale anche se si userà poi un linguaggio di alto livello. Poi, scelto un linguaggio, si traduce la soluzione, un pezzetto alla volta, nel linguaggio di programmazione; qui non ci si occupa più di “cosa fa” il pogramma nel suo complesso, ma di come si traducono passo passo nel linguaggio di programmazione i singoli pezzetti (dichiarazioni, if, loop eccetera). COMMENTO sui salti (per realizzare if, cicli eccetera): si possono usare in molti modi, più o meno astuti, le varie istruzioni e pseudoistruzioni. Suggerimento: dopo un po’ di esercizi, createvi il vostro “stile di programmazione” e usate sempre quello. 4