Beim Programmieren mit MMIX habt ihr vielleicht schon öfter eine der folgenden Fehlermeldungen von MMIXAL bekommen:

Ähnliche Dokumente
Technische Informatik II Rechnerarchitektur

Technische Informatik II Rechnerarchitektur

Übersicht. Quelle: Kapitel 3, 4 und 5 aus Anlauff, Böttcher, Ruckert: Das MMIX-Buch. Springer, 2002

Übungsblatt 10 (Block C 2) (16 Punkte)

Welche Register werden zur Parameterübergabe verwendet? In welcher Reihenfolge werden die Parameter auf dem Stack bzw. in den Registern abgelegt?

Der Intel 8086 Reto Gurtner 2005

ARM-Cortex-M4 / Thumb-2-Befehlssatz Adressierungsarten und arithmetische Operationen

SUB $2,$5,10 Zeile 1 LDO $5,$0,2*8 Zeile 2 OR $1,$2,$3 Zeile 3 SRU $1,$5,$1 Zeile 4.

Sprungbefehle und Kontroll-Strukturen

Programmiersprachen Einführung in C

T e) Welche Eigenschaft müssen Byte-, Wyde-, Tetra- und Octa-Adressen beim MMIX haben?

Offenbar hängt das Ergebnis nur von der Summe der beiden Argumente ab...

Assembler DOS (Beta 1) Copyright 2000 Thomas Peschko. Assembler II - DOS. ASSEMBLER Arbeiten mit Dateien und Daten.

Übung Praktische Informatik II

1 Rechnerstrukturen 1: Der Sehr Einfache Computer

Mikroprozessoren Grundlagen AVR-Controller Input / Output (I/O) Interrupt Mathematische Operationen

Assembler - Adressierungsarten

MMIX Crashkurs Teil 3 Unterprogramme und Parameterübergabe. Freiling/Wienzek/Mink Vorlesung Rechnerstrukturen RWTH Aachen Sommersemester 2005

1 pulsierender Speicher

A ProgrAmmer s Guide to KIM Programming

GI Vektoren

PicAxe M2 - Das Speicherkompendium. Ausgabe Matthias Heuschele / SSE

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

2. Programmierung in C

MMIX - Crashkurs. TI-II Rechnerarchitektur

5.1 Beschreibung des Prozessors M Programmierung in Maschinensprache. 5.1 Beschreibung des Prozessors M 68000

5. Programmierung in Maschinensprache

, 2014W Übungsgruppen: Mo., Mi.,

"Organisation und Technologie von Rechensystemen 4"

Probeklausur Name: (c)

Systeme I: Betriebssysteme Kapitel 8 Speicherverwaltung

Von Assembler zu Java

Inhalt. 4.5 Arbeit mit Zeigern (engl. Pointer)

T c) Daten welcher Größenordnung kann ein Register aufnehmen: Byte, kilobytes, megabytes, gigabytes or terabytes?

H S R R a p p e r s w i l \0

Selbststudium Informationssysteme - H1102 Christian Bontekoe & Felix Rohrer

Technische Informatik I - HS 18

32 Bit Konstanten und Adressierung. Grundlagen der Rechnerarchitektur Assembler 78

6 MMIX-Prozessor. 6.1 Programmiermodell. S.219 alles wichtig. 6.2 Register. Allzweckregister

Stack, Stackpointer, Unterprogramm HP: 0 * 1 * 2 * 3 CAL UP1 4 * 5 * 6 CAL UP2 7 *... UP1: 30 * 33 RET UP2: 40 * 41 CAL UP1 42 * 43 RET

4. TÜ-Zusammenfassung zum Modul Computersysteme

Proseminar Konzepte von Betriebssystem- Komponenten (KVBK) Vortrag zum Thema: Speicheraddressierung, Segmentierung, Paging

Rechnerstrukturen 1: Der Sehr Einfache Computer

Lösungsvorschlag 9. Übung Technische Grundlagen der Informatik II Sommersemester 2009

Übung Praktische Informatik II

5 Speicherverwaltung. bs-5.1 1

T e) Wie wird im Speicher an der Adresse 0x die 32 Bit-Zahl

2.1 Fundamentale Typen

C - PRÄPROZESSOR. Seminar effiziente C Programmierung WS 2012/13. Von Christian Peter

Zwei Möglichkeiten die TLB zu aktualisieren

8. Referenzen und Zeiger

Funktionen in JavaScript

Lösung 5. Übungsblatt

Übersicht. Speichertypen. Speicherverwaltung und -nutzung. Programmieren in C

Mikrocomputertechnik. Adressierungsarten

JavaScript. Dies ist normales HTML. Hallo Welt! Dies ist JavaScript. Wieder normales HTML.

Zeiger (engl. Pointer)

Zusammenfassung der Assemblerbefehle des 8051

IM P label = Bedingte Verzweigungen

Proseminar Konzepte von Betriebssystem-Komponenten (KVBK) Vortrag zum Thema: Speicheraddressierung, Segmentierung, Paging Von Christian Hubert

Probeklausur Programmieren in C Sommersemester 2007 Dipl. Biol. Franz Schenk 12. April 2007, Uhr Bearbeitungszeit: 105 Minuten

Übungsblatt 1. Java Vorkurs (WS 2017)

Assembler (NASM) Crashkurs von Sönke Schmidt

Funktionen in JavaScript

Übersicht Shell-Scripten

Kap.3 Mikroarchitektur. Prozessoren, interne Sicht

Von-Neumann-Architektur

Mikrocomputertechnik. Unterprogramm

Arrays,Strings&Pointer in C/C++

Rechnernetze und Organisation

Variablen, Konstanten und Datentypen

Lesen Sie alle Aufgabenstellungen sorgfältig durch, bevor Sie mit der Bearbeitung der ersten Aufgabe beginnen.

10. Die Adressierungsarten des MSP 430

Funktionen: Rückgabewert

UNTERPROGRAMME IN MMIX(AL)

MMIX: Einführung. Einführung. Ressourcen. Aussprache: em-micks Autor: Donald Knuth

Grundlagen der Rechnerarchitektur. MIPS Assembler

3AA. Prof. Dr. Wolfgang P. Kowalk. Universität Oldenburg WS 2005/2006

1. TÜ-Zusammenfassung zum Modul Computersysteme

9. Assembler: Der Prozessor Motorola 68000

9. Assembler: Der Prozessor Motorola 68000

LOC Data_Segment A OCTA a) Bestimmen Sie das 32 Bit breite Befehlswort des Befehls JMP Start.

Lösungsvorschlag zur 3. Übung

9. Die Adressierungsarten des MSP 430

Der Toy Rechner Ein einfacher Mikrorechner

Praktikumsprotokoll Mikrorechentechnik I Versuch

Datenpfad einer einfachen MIPS CPU

Grundlagen der OO- Programmierung in C#

Computersysteme. Stacks Anwendung in der Assembler-Programmierung

TI II. Sommersemester 2009 Prof. Dr. Mesut Güneş 7. Aufgabenblatt mit Lösungen

10.4 Konstante Objekte

Organisatorisches. Folien (u.a.) gibt's auf der Lva-Homepage zum Download

Adressierungsarten des 6809 (Forts.)

Die Klasse string Verfasser: Christian Bartl

Informatik Rechnerinterne Vorgänge: Programmstrukt. (Lsg.) Gierhardt

Technische Informatik 1 Übung 2 Assembler (Computerübung) Matthias Meyer

Zeichenketten (1) Literale von Zeichenketten werden in doppelte Anführungszeichen gesetzt

Transkript:

1 ADRESSIERUNG IN MMIX Beim Programmieren mit MMIX habt ihr vielleicht schon öfter eine der folgenden Fehlermeldungen von MMIXAL bekommen: no base address is close enough to the address A! relative address is more than #ffff tetrabytes forward! Diese Fehler können z.b. bei der Adressierung von Speicher oder bei Branches / Jumps auftreten. Um diese Fehler verstehen zu können, muss man sich etwas detaillierter mit der Funktionsweise von MMIX und den einzelnen Befehlen auseinandersetzen. AUFBAU EINES PROGRAMMS Ein MMIX-Programm sollte grundsätzlich so aufgebaut sein: 1 lege alle Daten im Speicher ab der Adresse #2000000000000000 ab 2 GREG @ erzeuge ein globales Register mit der Speicheradresse dieser Zeile 3... 4 DATEN lege Daten an 5... 6 Code wird ab Speicheradresse #0000000000000100 abgelegt 7 Main BEFEHL Hier wird das Programm gestartet 8... 9 BEFEHLE 10... 11 Label BEFEHLX Ein Label, d.h. die Speicheradresse von BEFEHLX kann über Label angesprochen werden 12... 13 TRAP 0,Halt,0 Ende des Programms ERKLÄRUNG ZU WICHTIGEN BEFEHLEN LOC @ GREG XYZ Die Pseudo-Anweisung LOC XYZ veranlässt MMIXAL (MMIX Assembly Language) die folgenden Anweisungen an der Speicheradresse XYZ abzulegen. Data_Segment ist eine Konstante von MMIXAL und hat den Wert #20.. (noch 14 Nullen). Durch die Verwendung von LOC in den Zeilen 1 und 6 erhält man das folgende Speicherbild: ab Beginn der Adresse Inhalt des Speichers #00..000 nichts #00..100 Code / Befehle #20..000 Daten #FF..FFF Ende des Speichers Das @ steht in MMIXAL immer für die aktuelle Position im Speicher. Die Pseudo-Anweisung legt ein globales Register an, in das der WERT XYZ geschrieben wird. Die Zeile GREG @ legt also ein globales Register an, in das die aktuelle Speicherposition geschrieben wird. Globale Register sind Register

2 wie $255, über die z.b. mit dem Betriebssystem Parameter für die Ein- oder Ausgabe ausgetauscht werden. Eine weitere Anwendung von globalen Registern wird weiter unten erklärt. JMP label Der Befehl JUMP (JMP) veranlasst den Rechner die Ausführung von Befehlen an der Speicheradresse label fortzuführen. Ein Label ist wie in Zeile 11 eine einfache Markierung. BX $X,label Branch-Befehle beginnen immer mit einem B. Über diese kann man den Ablauf des Programms beeinflussen und so genannte konditionale Sprünge durchführen. Branches werden also nur durchgeführt, wenn eine bestimmte Bedingung erfüllt ist. Wohin das Programm springen soll, wird durch die Angabe einer Speichermarke, einem label, angegeben. Ob ein Sprung durchgeführt wird oder nicht hängt dabei von der Befehlsart und dem Inhalt des Registers X ab. Beispiele für Branch-Befehle sind u.a. BZ und BP. BZ steht für Branch if zero. BZ $1,label bedeutet daher: Springe zu label, wenn der Inhalt des Registers 1 gleich 0 ist. GETA $X,label Lädt die Adresse der Speichermarke label in das Register X. LDA $X,label Lädt die Adresse der Speichermarke label in das Register X unter der Verwendung eines globalen Registers, das von MMIXAL eingesetzt wird. LDX[U] $I,$J,$K K Über die LOAD-Befehle (beginnend mit LD) können Daten aus dem Speicher gelesen werden. Es gibt dabei wieder verschiedene Varianten: LDB, LDW, LDT, LDO, LDBU etc. Der Aufbau dieser ist immer gleich. Beginnend mit dem LD beschreibt das nächste Zeichen, wie groß der Speicherbereich ist, der geladen werden soll. Ein B steht für, ein W für ein Wyde, etc. Das letzte optionale U gibt darüber hinaus noch an, ob das Datum an der Speicheradresse als unsigned angesehen werden soll, also nicht vorzeichenbehaftet ist. Die Parameter von LDX[U] sind in der Regel drei Register. In das Register I soll der Wert geschrieben werden. Die Summe der Register J und K geben die Speicheradresse an, aus der die Daten gelesen werden sollen. Als dritter Parameter kann auch eine Konstante geschrieben werden. BEFEHLE ZUR ADRESSIERUNG IN MMIX Bei den Befehlen für Sprünge / Branches, das Laden von Adressen und dem Laden von Daten muss immer eine Speicheradresse angegeben werden. Eine falsche Adressierung kann zu den oben angesprochenen Fehlern führen. Um ein Verständnis dieser Fehlermeldungen und deren Lösungen zu schaffen, muss der Aufbau der einzelnen Befehle verstanden werden. Ein Befehl besteht aus 4 s und ist immer wie folgt aufgebaut: 0 1 2 3 Argument X Argument Y Argument Z Argument X Argument YZ Argument XYZ Der beschreibt den Befehl, der auszuführen ist. Wie man der Tabelle entnehmen kann, können maximal 3 Argumente übergeben werden. Diese sind jeweils ein groß. Werden ein oder zwei Argumente angegeben, stehen für die Argument(e) 1&2 oder 3 s zur Verfügung.

3 ART DES SPEICHERZUGRIFFS Es wird zwischen relativer und absoluter Adressierung unterschieden. Bei der relativen Adressierung wird die Adresse durch eine Verschiebung in Bezug auf die aktuelle Adresse beschrieben. Im Gegensatz dazu wird bei der absoluten Adressierung eine absolute Speichadresse zur Adressierung benutzt. BEISPIEL RELATIVE ADRESSIERUNG Speicheradresse Code #100 Main SET foo,100 #200 Loop SUB foo,foo,1 #300 BZ foo,loop Wird der Branch genommen, so wird der Programcounter auf @ - #100 gesetzt. Es wird also auf die aktuelle Position Bezug genommen und eine Verschiebung von -100 festgelegt. BEISPIEL ABSOLUTE ADRESSIERUNG Speicheradresse Code GREG @ #20..00 msg BYTE Hallo!,0 #100 Main SET foo,100 #200..LDA $1,msg Hier wird die Speicheradresse als absoluter Wert #20..00 nach $1 geladen. (Wie das genau funktioniert wird weiter unten beschrieben!)

4 WIE ADRESSIERT MAN RICHTIG? Mittels der relativen Adressierung kann nicht der gesamte Speicher adressiert werden. Dies ist auf den Aufbau der Befehle zurückzuführen. So kann den Branch-Befehlen und GETA als Verschiebung zur derzeitigen Adresse nur ein 16 Bit Wert übergeben werden. Dies entspricht einer maximalen Verschiebung um #FFFF = 65535 viele Zeilen Code à 4 (jeder Befehl hat 4 ). Befehl 0 1 2 3 GETA $X,label von GETA BZ $X,label von BZ Angabe des Registers Angabe des Registers Angabe der Verschiebung zur aktuellen Speicherposition Angabe der Verschiebung zur aktuellen Speicherposition Der Befehl JMP hingegegen hat nur einen Parameter und kann somit 3 = #FFFFFF = 16777215 viele Codezeilen entfernt springen. Erhält man die eingangs erwähnte Fehlermeldung relative address is more than #ffff tetrabytes forward! bedeutet dies also, dass die Adressierung mittels 2 nicht dargestellt werden kann. In dem folgenden nicht funktionstüchtigen Beispiel wird dies gezeigt: msg Main BYTE Hallo,0 GETA $1,msg FEHLER! Der Fehler ist hier offensichtlich. An der Stelle #100 im Speicher wird die erste Zeile Code abgelegt. Die Daten wurden davor an der Stelle #2000000000000000 abgelegt. Um in der ersten Zeile die msg adressieren zu können, müsste also eine relative Adresse eingesetzt werden, welche größer als der mittels 2 repräsentierbare Wert wäre. MMIXAL kann diesen Code nicht übersetzen. Um weiter entfernte Speicherbereiche adressieren zu können, was besonders für das Laden und Speichern von Daten von Bedeutung ist, wird deshalb auf absolute Adressierung zurückgegriffen. msg Main BYTE Hallo,0 LDA $1,msg FEHLER! Auch dieser Code führt jedoch zu einem Fehler. Die Funktion LDA erhält nämlich eigentlich 3 Argumente:

5 Befehl 0 1 2 3 LDA $X,$Y,$Z Z von LDA Angabe des Zielregisters für das Ergebnis Angabe eines Registers Angabe eines Registers oder einer Konstante Gemäß dieser eigentlichen Variante des LDA-Befehls wird die Adresse aus der Summe des Inhalts von $Y und $Z berechnet. Ein Beispiel verdeutlicht diese Vorgehensweise: greg GREG @ PI TETRA 31415926 msg BYTE Hallo,0 Main LDA $1,gReg,4 Wie oben beschrieben wird durch GREG @ in ein globales Register der Wert der aktuellen Speicherpostion in diesem Falle #2000000000000000 geschrieben. Durch das vorgestellte greg können wir auch im weiteren Programmverlauf das globale Register benennen. In der ersten Zeile des Codes laden wir nun die Adresse von msg in den Speicher: In greg steht die sogenannte Basisadresse #2000000000000000. Da vor der msg noch ein Tetra abgelegt wurde, addieren wir zur Basisadresse 4 um auf den richtigen Speicherplatz zuzugreifen. Fertig! Die Verwendung von Registern mit 64 Bit erlaubt daher eine vollständige Adressierung aller 64 2 Speicherzellen. Zugegebenermaßen: Diese Technik ist mehr als hässlich und würde die Verwendung von MMIXAL sehr unschön gestalten (siehe Bild). Die Lösung in MMIXAL wurde oben schon kurz vorgestellt: Anstatt die Adresse per Hand zu errechnen, übergeben wir nur das Label: GREG @ PI TETRA 31415926 msg BYTE Hallo,0 Main LDA $1,msg Wie ist das möglich? MMIXAL nimmt uns die Arbeit ab und schreibt unseren LDA Befehl bei dem Compilieren in die obere Variante um. MMIXAL sucht eigenständig das richtige globale Register, was wir trotzdem per Hand anlegen müssen, heraus und berechnet die richtige Verschiebung zu diesem Register. Für uns als Programmierer ist dieser Vorgang transparent, und wir merken uns nur folgenden (Pseudo-)Befehl: Befehl 0 1 2 3 LDA $X,label von LDA Angabe des Zielregisters für das Ergebnis Angabe eines Labels, welches im Umfeld der Erzeugung eines globalen Registers liegt

6 Findet MMIXAL kein globales Register, mit einer Basisadresse, welche benutzt werden kann, wird die Fehlermeldung no base address is close enough to the address A! ausgegeben. Mittels der gleichen Technik können nun auch Daten aus dem Speicher geladen werden: Lege Segment für Daten an GREG @ Erzeuge globales Register mit aktueller Speicherposition baseadr IS $1 char IS $0 PI TETRA 31415926 msg BYTE Hallo,0 Erzeuge String Beginne mit Code Main LDA baseadr,msg Lade die Adresse von msg nach $0 LDB char,baseadr,4 Lade das fünfte Zeichen der Zeichenkette (das o) in Register $1 Anstatt bei LDB die Konstante 4 zu verwenden, kann natürlich auch wieder ein Register benutzt werden.