from programlaster import Programlaster from hovedminne import Hovedminne class LMC: """ simulerer selve prosessoren som kjører programmet i minnet """ def __init__(self, ram): """ oppretter registrene og kobler prosessoren til minnet """ self._programteller = 0 self._instruksjonspeker = 0 self._minneadresseregister = 0 self._akkumulator = 0 self._ram = ram self._kjorer = True self._instruksjoner = { 0: self.hlt, 1: self.add, 2: self.sub, 3: self.sta, 5: self.lda, 6: self.bra, 7: self.brz, 8: self.brp, 9: self.inp_out, } def _sett_gyldig_verdi(self, verdi): """ holder akkumulatorverdien innenfor -999 til 999 """ if verdi > 999: verdi %= 1000 elif verdi < -999: verdi = -(abs(verdi) % 1000) return verdi def hlt(self, adresse): """ stopper programmet """ self._kjorer = False def add(self, adresse): """ legger verdien i minnet til akkumulatoren """ self._minneadresseregister = adresse self._akkumulator += self._ram.hent_innhold(self._minneadresseregister) self._akkumulator = self._sett_gyldig_verdi(self._akkumulator) self._programteller += 1 def sub(self, adresse): """ trekker verdien i minnet fra akkumulatoren """ self._minneadresseregister = adresse self._akkumulator -= self._ram.hent_innhold(self._minneadresseregister) self._akkumulator = self._sett_gyldig_verdi(self._akkumulator) self._programteller += 1 def sta(self, adresse): """ lagrer akkumulatoren i minnet """ self._minneadresseregister = adresse self._ram.sett_innhold(self._minneadresseregister, self._akkumulator) self._programteller += 1 def lda(self, adresse): """ henter en verdi fra minnet til akkumulatoren """ self._minneadresseregister = adresse self._akkumulator = self._ram.hent_innhold(self._minneadresseregister) self._programteller += 1 def bra(self, adresse): """ hopper alltid til den gitte adressen """ self._programteller = adresse def brz(self, adresse): """ hopper dersom akkumulatoren er 0 """ if self._akkumulator == 0: self._programteller = adresse else: self._programteller += 1 def brp(self, adresse): """ hopper dersom akkumulatoren er positiv eller 0 """ if self._akkumulator >= 0: self._programteller = adresse else: self._programteller += 1 def inp(self, adresse): """ leser inn et heltall til akkumulatoren """ self._akkumulator = int(input()) self._akkumulator = self._sett_gyldig_verdi(self._akkumulator) self._programteller += 1 def out(self, adresse): """ skriver ut akkumulatoren """ print(self._akkumulator) self._programteller += 1 def otc(self, adresse): """ skriver ut akkumulatoren som et ASCII-tegn """ print(chr(self._akkumulator), end="") # end="" ungår linjeskift self._programteller += 1 def inp_out(self, adresse): """ skiller mellom INP (901), OUT (902) og OTC (922) """ if adresse == 1: self.inp(adresse) elif adresse == 2: self.out(adresse) elif adresse == 22: self.otc(adresse) else: self._kjorer = False print(f"Ukjent IO-instruksjon 9{adresse}.") def interpret(self): """ henter og utfører instruksjoner til programmet stopper """ while self._kjorer: self._instruksjonspeker = self._ram.hent_innhold(self._programteller) operasjonskode = self._instruksjonspeker // 100 minneadresse = self._instruksjonspeker % 100 # Henter instruksjonsmetoden fra ordbboken, og kaller den med minneadressen self._instruksjoner[operasjonskode](minneadresse) def hovedprogram(): """ leser et program, laster det inn i minnet og kjører det """ programlaster = Programlaster() minne = programlaster.les_program("selvmodifiserendekode.txt") ram = Hovedminne(100) ram.last_innhold(minne) lmc = LMC(ram) lmc.interpret() hovedprogram()