Programmiersprachen
LVA 185.208, VL 2.0, 2009 S
1. Übungsaufgabe
AKTUELL:
Im unten vorgegebenen Befehlssatz des Geräts gibt es keinen Befehl, um ein indirekt adressiertes Register auszulesen.
Vermutlich würde Ihnen ein solcher Befehl die Lösung der Aufgabe wesentlich erleichtern.
Sie können die Aufgabe so abändern, dass Sie einen solchen Befehl einführen und dafür einen beliebigen anderen Befehl, den Sie nicht brauchen, weglassen.
Aufgabe:
Entwickeln Sie in einer Programmiersprache Ihrer Wahl eine Simulation eines programmierbaren Geräts (bzw. Taschenrechners) entsprechend folgenden Spezifikationen.
Nur die wichtigsten Grundfunktionen sind in der von Ihnen gewählten Programmiersprache zu implementieren.
Alles andere ist direkt in der Sprache des Werkzeugs zu realisieren.
Architektur des Geräts:
Das Gerät besteht aus folgenden Teilen:
- Insgesamt 16384 addressierbare Register zu je 32 Bit haben Adressen von -8192 bis 8191.
- Die Recheneinheit operiert direkt auf den Registern.
Die ausgeführten Befehle liegen ebenfalls in den Registern.
Register -8192 enthällt die Adresse des Registers mit dem nächsten Befehl (program counter).
- Der Flash-Speicher (simuliert durch eine Datei) hat eine fixe Größe, die von Ihnen wählbar ist.
Dieser Speicher kann nur in einzeln adressierbaren Blöcken von je 512 Byte über einen Puffer gelesen und geschrieben werden.
- Die Anzeigeeinheit stellt 4 Zeilen zu je 32 Zeichen dar.
Es werden stets die Zeichen in den untersten 7 Bit (oder 8 Bit, je nachdem, welche Kodierung Sie wählen) der Register 8064 bis 8191 angezeigt.
- Die Initialisierungseinheit kopiert nach dem Einschalten des Geräts die ersten 128 Blöcke aus dem Flash-Speicher und initialisiert damit alle Register.
Befehle (in Registern) bestehen aus 32 Bit und haben die Struktur oBA, wobei o aus 4 Bit besteht und die Operation bestimmt und B und A aus je 14 Bit bestehen und Registeradressen bzw. Konstanten beschreiben.
Folgende Operationen sollen unterstützt werden:
- Schreibe B (als Konstante) in Register A (bzw. springe zur Adresse B für A = -8192)
- Schreibe den Ihnalt von Register B in Register A (bzw. indirekter Sprung für A = -8192)
- Schreibe B (als Konstante) in ein Register, dessen Adresse durch den Inhalt von Register A bestimmt wird
- Schreibe den Ihnalt von Register B in ein Register, dessen Adresse durch den Inhalt von Register A bestimmt wird
- Addiere B (als Konstante) zum Inhalt von Register A und speichere das Ergebnis im Register A (bzw. relativer Sprung für A = -8192)
- Addiere B (als Konstante) zu Register -8192 falls Register A einen Wert ungleich 0 enthällt, sonst mache nichts (bedingter relativer Sprung)
- Addiere den Inhalt von Register B zum Inhalt von Register A und speichere das Ergebnis im Register A
- Subtrahiere den Inhalt von Register B vom Inhalt von Register A und speichere das Ergebnis im Register A
- Multipliziere B (als Konstante) mit dem Inhalt von Register A und speichere das Ergebnis im Register A
- Multipliziere den Inhalt von Register B mit dem Inhalt von Register A und speichere das Ergebnis im Register A
- Dividiere den Inhalt von Register A durch B (als Konstante) und speichere das Ergebnis im Register A
- Dividiere den Inhalt von Register A durch den Inhalt von Register B und speichere das Ergebnis im Register A
- Springe zur Adresse B (das heißt, schreibe B als Konstante in Register -8192) falls Register A einen Wert ungleich 0 enthällt, sonst mache nichts
- Lies ein Zeichen von der Tastatur, speichere es in Register A und springe zur Adresse B (schreibe B als Konstante in Register -8192) falls eine Eingabe gemacht wurde, sonst mache nichts
- Schreibe den Inhalt eines aus 128 aufeinanderfolgenden Registern bestehenden Puffers in den Flash-Speicher, wobei B die konstante Adresse des Puffers und A die Adresse eines Registers ist, dessen Inhalt die Nummer des geschriebenen Blocks im Flash angibt
- Lies einen Block aus dem Flash in einen aus 128 aufeinanderfolgenden Registern bestehenden Puffer, wobei B die konstante Adresse des Puffers und A die Adresse eines Registers ist, dessen Inhalt die Nummer des gelesenen Blocks im Flash angibt
Alle arithmetischen Operationen sind ganzzahlig und interpretieren Registerinhalte als vorzeichenbehaftete Zahlen.
A und B sind ebenfalls vorzeichenbehaftete Konstanten oder Registeradressen.
Software auf dem Gerät:
Es wird Software für folgende Anwendungen benötigt:
- Taschenrechner, der die vier Grundrechnungen (+, -, *, /) auf ganzen Zahlen beherrscht (32 Bit) und die Eingaben sowie die Ergebnisse von Berechnungen in der Anzeigeeinheit darstellt.
Beim Abschalten den Geräts können die Daten des Taschenrechners verloren gehen.
- Adress- bzw. Telefonbuch, das die Suche nach Einträgen über Namen erlaubt.
Daten sollen beim Abschalten des Geräts erhalten bleiben.
- Werkzeug, das die Anzeige und Veränderung von Register- und Flash-Inhalten ermöglicht.
- Programmstarter, der es erlaubt, die am Gerät vorhandenen Anwendungen aufzurufen.
Diese Software soll direkt auf dem simulierten Gerät ausgeführt werden.
Daher ist sie ausschließlich über die oben beschriebenen Operationen zu implementieren.
Hinweise:
Das Gerät ähnelt in der Architektur üblichen Rechnern.
Es lässt sich wie andere Computer programmieren, allerdings wegen fehlender Werkzeuge nur auf einer sehr niedrigen Ebene.
Genau das ist die Herausforderung in dieser Aufgabenstellung.
Legen Sie den Schwerpunkt auf die Software, die auf dem Gerät benötigt wird (und nicht auf den relativ einfach zu implementierenden Simulator).
Gehen Sie am besten so vor:
- Schreiben Sie die Programme zuerst in einer höheren Programmiersprache.
Verzichten dabei aber auf komplexere Programmiertechniken wie Objekte oder Rekursion.
- Achten Sie von Anfang an darauf, dass die Software so einfach und kurz wie möglich bleibt.
Vor allem sollten Sie gemeinsame Programmteile zu Prozeduren zusammenfügen.
Verzichten Sie auf schöne Benutzerschnittstellen, Fehlerabfragen und alles, was den Code größer als unbedingt nötig machen würde.
- Probieren Sie die Programme aus und beseitigen Sie Fehler.
- Im letzten Schritt übersetzen Sie die Programme händisch und erzeugen dabei die Datei, die den Flash-Speicher darstellt.
Vermeiden Sie in diesem Schritt Optimierungen.
Die Anzahl der Register ist groß genug, sodaß Sie nicht besonders sparsam damit umgehen müssen.
Für den letzten Schritt können Sie Hilfsmittel verwenden.
Beispielsweise können die meisten C-Compiler Assembler-Code produzieren, der sich durch die Ähnlichkeit mit den Befehlen des Geräts vielleicht leichter übersetzen lässt als der Quellcode.