Revenge of LMC

I denne oppgaven og den neste skal vi fors?ke ? emulere LMC i Python. For de som eventuelt ikke har eller har hatt in1020 er LMC en simulator av en enkel prosessor og assembler. Dere kan teste det her: https://peterhigginson.co.uk/lmc/ Vi kommer og til ? ha en liten primer i de to neste gruppetimene, s? alle vet ca hvordan dette fungerer, og hva vi ?nsker ? oppn?.

Denne uka vil vi lage et program som lar oss lese og laste inn et program i minnet til LMC-emulatoren v?r og som sjekker at syntaksen til programmet som leses er noenlunde riktig. Dere finner kodeskjelettet i uke4-mappa p? emnesiden.

For de som ikke er her denne gangen, eller som ikke fikk fullf?rt oppgaven kommer vi til ? legge ut en "fasit" f?r neste time, slik at alle kan fortsette p? neste del neste uke.

F?r dere begynner

  1. Last ned filen lmc.py fra ukesiden. Den inneholder et kodeskjellett som inneholder litt mer forklaring p? metodene vi skal lage.
  2. Last ned filen add.txt og lagre den i samme mappe som du lagret lmc.py, dette er et enkelt LMC-program som skal brukes til den f?rste oppgaven. Gj?r det kjent med hvordan den filen ser ut f?r du begynner p? oppgavene.
  3. Last ned de resterende .txt-filene og lagre dem i den samme mappa.

Oppgave 1, lese en enkelt instruksjon

En LMC-instruksjon er et tre sifre tall, som man deler i to. Det f?rste sifferet er operasjonskoden, og de to neste tallene viser til en indeks i minnet. Vi kan modellere dette ved ? ha en liste med 100 elementer som representerer RAM. Dette er allerede opprettet i LMC.py for dere.

# Vi kan bruke gangertegnet til ? opprette en liste med x antall like elementer.
minne = [0] * 100

I denne oppgaven skal vi lage prosedyren les_program(programfil) som tar stien til en programfil som parameter (en av .txt-filene i mappa) og laster det inn i minnet. Vi skal begynne med ? kunne lese fila add.txt, som kun best?r av direkte instruksjoner.

1.1 lag_instruksjon

Det f?rste vi skal gj?re er ? skrive en prosedyre lag_instruksjon(instruksjon, operasjonskoder) som tar en liste best?ende av instruksjonen og eventuelt den p?f?lgende immidiate-verdien. Vi tar ogs? med en oversikt over hvilke operasjonskoder som svarer til hvilken numeriske verdi.

Vi skal ikke skille mellom store og sm? bokstaver. F.eks skal strengen "ADD 99" omformes til formen ["add", "99"], mens linja INP skal omformes til ["inp"].

Studer programkoden i add.txt:

        INP
        STA 99
        INP
        ADD 99
        OUT
        HLT

N?r vi leser inn programmet linje for linje vil vi jobbe med strenger p? formen "<INSTRUKSJON> <IMMEDIATE>", som for eksempel "ADD 99". F?r dere kaller metoden m? dere alts? bruke streng-operasjoner for ? f? strengen p? riktig format.

Hint strenger har funksjonene .lower() og .split() som kan v?re hendige her.

Returverdien skal v?re instruksjonsverdien som skal lagres i minnet. Alts? skal et kall p?:

lag_instruksjon(["add", "99"], operasjonskoder)

returnere 199

og

lag_instruksjon(["inp"], operasjonskoder)

returnere 901

Oppgave 2 les et program

N? skal vi lese inn programmet add.txt. N?r vi leser inn et program i LMC vil vi opprette hver instruksjon linje for linje inn i minnet. Alts? vil den f?rste instruksjonen bli plassert p? den f?rste plassen i minnet, og den 2. linja p? den 2. plassen i minnet osv. For ? gj?re dette skal dere bruke hjelpeprosedyren dere lagde i forrige oppgave til ? lage instruksjonsverdier, og s? plassere dem korrekt i minnet. Dere kan anta at alle instruksjoner kommer uten linjeskift.

Som en sjekk n?r dere er ferdige kan dere laste inn add-programmet i LMC-simulatoren p? nettsiden og forsikrer dere om at minnet dere oppretter og det som kommer inn i simulatoren er det samme.

Oppgave 3 merker

N? skal vi utvide programmet slik at vi ogs? kan h?ndtere merker. Bytt ut programmet dere skal lese med addsub.txt. Her finner dere merket FIRST som en del av programmet.

Merker brukes i assembly-kode til ? indikerer minneadresser (indeksene inn i lista v?r). Merker kan b?de markere spesifikke deler av koden en branch-instruksjon skal hoppe til eller hvor data programmet trenger er lagret. Merkene som er til venstre for instruksjoner er selve merkene, og merkene til h?yre skal erstattes med minneadressen til merket.

Et problem vi har i v?r implementasjon er at vi leser programmet i rekkef?lge slik det er i fila. Det betyr at vi ikke vet hva datamerket FIRST er n?r vi kommer over det p? linje to, s? vi vil ikke kunne gj?re det om til et heltall til lag_instruksjon. N?r man skal tolke tekster p? denne m?ten ender man derfor ofte opp med ? m?tte lese gjennom teksten mer enn en gang. P? f?rste gjennomlesning ?nsker vi ? finne ut hvilke merker vi trenger, og assosiere dem med et linjenummer i fila.

illusterer at merket som opprettes p? linje 10 brukes p? linje 2

3.1 lag_merker(programfil)

Som sist skal vi f?rst lage en hjelpeprosedyre for ? opprette merker, lag_merker(programfil). Denne prosedyren skal lese programfilen og returnere en datastruktur som assosierer et merke med en minneadresse.

3.2 les_program

N? vil dere og merke at ? lese instruksjoner ikke lenger fungerer som det skal. Vi trenger ? h?ndtere merkene i lag_instruksjon, siden instruksjonene v?re n? kan se slik ut ["sta", "first"] eller ["first", "dat"]. Merker som f?rste element betyr dette merket skal finnes i oversikten over merker, merker som siste element betyr erstatt med minneadressen som er assosiert med merket.

Dersom programmet deres er riktig skal det n? v?re i stand til ? lese alle testprogrammene som er i mappen, men det er greit hvis det ikke klarer ? lese factorial.txt.

Oppgave 4 feilh?ndtering

N?r man skal tolke et program er det fint om man f?r fornuftige feilmeldinger n?r noe ikke fungerer slik programmereren har tenkt. Derfor skal vi utvide innlesningen til ? og h?ndtere noen vanlige feil som kan bli gjort. Vi skal bruke assert til ? lage feilmeldinger.

# Assert sjekker at en eller annen sannhetsverdi er True, ¨
# hvis ikke skrives feilmeldingen ut sammen med ASSERTION ERROR og programmet avsluttes.

assert linjeteller < 100, "Et LMC-program kan maksimalt inneholde 100 instruksjoner"

4.1 Gjennbruk av merker

Hvis det samme merket opprettet flere ganger vil programmet neppe fungere som man vil, derfor skal prosedyren lag_merke kreve at merkene ikke allerede er opprettet, og hvis det er det skal den skrive en feilmelding som indikerer hvilket merke det er snakk om, og hvor det er brukt f?r.

Endre filen addsub.txt til ? og ogs? opprette merket FIRST p? linje 6 for ? sjekke om det fungerer.

4.2 ugyldige instruksjoner

Dersom lag_instruksjon f?r inn et argument som ikke er en gyldig instruksjon skal det og lages et unntak. Alle lovlige instruksjoner finnes i ordboken, s? vi kan kreve at det stemmer. Hvis ikke skal vi skrive en fornuftig feilmelding til programmereren. Endre ett av programmene til ? inneholde en ugyldig instruksjon for ? sjekke at det fungerer. For ? oppn? dette m? vi utvide prosedyren til ? og ta inn linjenummer som parameter.

4.3 ugyldige instruksjonsverdier

Siden LMC bare kan h?ndtere instruksjoner p? 3 siffer kan ikke tallene som opprettes i minnet v?re st?rre enn 999. For at en instruksjon skal v?re gyldig kan vi heller ikke godta at immidiate-verdiene er st?rre enn 99, da den da ruller over til ? bli en annen instruksjon. Dette skal og f?re til en feilmelding som indikerer p? hvilken linje feilen oppstod.

4.4 andre feil?

Er det andre feil som kan oppst? dere kan sjekke for?