In questa parte analizzeremo l’istruzione più delicata presente nel pdp8, ovvero quella che carica il contenuto del codice assembly, trasformandolo in codice macchina, nel nostro calcolatore didattico. Vedremo anche alcune funzioni utili per controllare lo stato della macchina durante l’esecuzione.
Ho già apportato le modifiche suggerite nel precedente articolo, di conseguenza il codice dovrebbe essere ancora più comprensibile. Non ho convertito il core per funzionare con gli interi, ma questa scelta è prettamente personale, poiché abbiamo già visto che porterebbe un incremento di prestazioni, che comunque non è rilevante ai fini del programma, del quale mi interessava sopratutto il funzionamento.
Codice
defcarica(self,codice,master):
"""
Carica il codice assembly in memoria.
Non si conta l'ultimo END, che corrisponde al fine programma.
La funzione ritorna 1 se il caricamento va a buon fine, None altrimenti.
"""
self.halt =False# warning se l'istruzione HLT non viene trovata
Ritorna una stringa con lo stato dell'unita' di controllo
"""
stringa =''
stringa +=("\n"+"--- UC ------"+"\n")
stringa +='S =\t'+str(self.S)+'\n'
stringa +='F =\t'+str(self.F)+'\n'
stringa +='R =\t'+str(self.R)+'\n'
stringa +='Int =\t'+str(self.Interrupt)+'\n'
stringa +=("-------------""\n")
returnstringa
Analisi
– La funzione carica riceve in input il codice da caricare (codice) e la finestra dell’editor (master). Quest’ultima è stata aggiunta in un secondo momento, poiché ora la funzione visualizza un finestra di warning a seconda dell’errore commesso (sempre tramite tkinter).
Il file di testo viene passato alla funzione eliminando gli spazi all’inizio, quindi utilizziamo rstrip per togliere quelli alla fine e memorizziamo il codice in una variabile temporanea.
Una volta diviso il codice per righe tramite split(‘\n’), ripuliamo ogni stringa ed infine anche la lista di stringhe da caratteri indesiderati.
Fatto questo, creiamo una lista cod che conterrà i codici da tradurre. Per inserirli correttamente, eliminiamo i commenti e aggiungiamo solo quello che ci serve alla lista. Finito questo, eliminiamo elementi indesiderati dalla lista.
Ora che abbiamo i nostri codici, controlliamo se all’inizio è presente la stringa ORG e settiamo di conseguenza la variabile START, per indicare da quale indirizzo si inizierà a memorizzare il programma. Se l’ORG non è corretto, si interrompe e si mostra una finestra di warning. Abbiamo anche creato una variabile temporanea per la ram (un dizionario per la precisione).
Il controllo successivo, consiste nel trovare l’END del file, se non presente si ritorna errore come prima. Da notare che END si deve trovare necessariamente nell’ultima posizione, ovvero quella di index n-1 dove n è il numero degli elementi della lista cod. Visto che dovrebbe essere utilizzato solo per indicare la fine del file, non controllo se l’utente lo utilizza nel codice, ma in tal caso ristituirebbe comunque errore perché non si trova solo alla fine del file e l’idex quindi non sarà quello dell’ultimo elemento, ma di un elemento all’interno di cod.
Successivamente memorizziamo i codici nella ram temporanea in base al loro indirizzo. Essendo prevista la presenza di più ORG, utilizzo un contatore (count) per determinare la cella del codice da scrivere partendo da start. Origin terrà traccia del valore iniziale di START, poiché sarà soggetto a mutamenti e quindi dovrà essere ripristinato alla fine.
Una volta creata la ram temporanea possiamo riempire la tabella dei Labels, associando ogni etichetta al suo indirizzo fisico (si parla sempre della memoria del nostro calcolatore). Eliminiamo dunque le etichette dalla ram temporanea, lasciando solo i codici veri e propri (tempRAM[x]=temp[1]).
Una volta copiata la ram temporanea nella ram vera e propria (si intende sempre quella del calcolatore didattico), si procede all’ultima conversione dei codici assembly in stringhe binarie. Di norma le stringhe avranno due o tre istruzioni e quindi verranno tradotte in base a quello che è presente nella stringa. Per prima però si controlla se indicano un numero espresso in valore decimale (DEC) oppure in esadecimale (HEX).
Si conclude estendendo le stringhe nella ram a 16 bit (se rappresentate con meno) ed aggiornando la ‘tabella’ dei breakpoints. Infine si controlla se l’istruzione HLT è stata trovata.
– Decode trasforma in binario i codici passati, controllando prima se sono indirizzi presenti nei labels, poi se sono istruzioni, altrimenti tratta quello che trova come se fosse un numero esadecimale e lo converte in binario. In questa funzione viene anche gestito il ritrovamento di HLT, che tecnicamente è solo un avvertimento, visto che il warning per HLT non blocca lesecuzione ma ritorna successivamente 1 (nella funzione carica carica).
– Le altre funzioni dovrebbero essere semplici da capire, visto che hanno solo il compito di stampare a video quello che è presente nel pdp8. Se avete provato il programma, noterete che l’unica funzione necessaria è statusRAM (per quel che riguarda l’interfaccia grafica), le altre sono solo necessarie se si utilizza la riga di comando. Infatti, durante la stesura del programma, controllavo la sua esecuzione tramite queste funzioni, visto che ancora non avevo implementato un’interfaccia grafica.
Conclusioni
Questa parte è stata la più delicata e fondamentale per tutto il progetto. Risente delle scelte prese inizialmente e condiziona pesantemente i passi successivi. Spero di essere stato comprensibile e di avervi dato un’idea di quello che fa l’emulatore per caricare un file assembly. Badate bene che questo è molto lontano dal lavoro che svolge un vero e proprio assembler, ma comunque ci si avvicina, se non altro come logica. Nel prossimo articolo vedremo come è gestita l’esecuzione del pdp8 per poi passare all’interfaccia grafica.
In Appunti Digitali cerchiamo di esprimere punti di vista informati su questioni che conosciamo, materie che pratichiamo professionalmente o passioni seguite a lungo e con metodo. Nei limiti del poco tempo che possiamo dedicare alla scrittura di articoli, speriamo di aiutarvi a costruirvi un’opinione su materie complesse, informarvi e se possibile divertirvi. I conti del server li paghiamo di tasca nostra e ci riserviamo perciò di moderare i commenti a nostra discrezione.