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

Ähnliche Dokumente
B1 Stapelspeicher (stack)

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

x86 Assembler Praktische Einführung Sebastian Lackner Michael Müller 3. Juni 2013

Karlsruher Institut für Technologie

Technische Informatik 1 Übung 2 Assembler (Rechenübung) Georgia Giannopoulou (ggeorgia@tik.ee.ethz.ch) 22./23. Oktober 2015

Betriebssystembau. 7. Übung. Michael Engel Arbeitsgruppe Eingebettete Systemsoftware. Lehrstuhl für Informatik 12 TU Dortmund

2. Aufgabenblatt mit Lösungen

Nachfolgende Abbildung zeigt das Spezialregister ra, das Arithmetische Status Register. Interrupt Enable (Freischalten)

Übungen für die Einführung in die Assemblerprogrammierung mit dem Prozessor c515c

Stephan Brumme, SST, 2.FS, Matrikelnr

4.2 Universalrechner: Schaltung unabhängig vom Problem 185

Übungscomputer mit Prozessor Bedienungsanleitung

Objektorientiertes Programmieren für Ingenieure

Funktionen in PHP 1/7

Mikrocomputertechnik - Programmierung

Grundlagen der Programmiersprache C++

Rechnerarchitektur Atmega Vortrag Atmega 32. Von Urs Müller und Marion Knoth. Urs Müller Seite 1 von 7

Technische Informatik 2 Maschinenprogrammierungskonzepte

IT- Handbuch für Fachinformatiker, 7. Auflage: Text- Lösungen Sascha Kersken

Assembler und Hochsprachen

Technische Informatik 2 Adressierungsarten

Die Mikroprogrammebene eines Rechners

Übungspaket 19 Programmieren eigener Funktionen

Übungspaket 31 Entwicklung eines einfachen Kellerspeiches (Stacks)

Algorithmen und Datenstrukturen (ESE) Entwurf, Analyse und Umsetzung von Algorithmen (IEMS) WS 2012 / Vorlesung 9, Dienstag 18.

Wie arbeiten Computer?

Objektorientierte Programmierung mit C++ Zusammenfassung der wichtigsten Topics rund um die objektorientierte Programmierung mit C++11

Systemsicherheit (SS 2015) 30. April Übungsblatt 2. Buffer-Overflow-Angriffe

Wer in der Grundschule ein wenig aufgepasst hat, sollte in der Lage sein schriftlich eine Zahl durch eine zweite zu teilen.

3 Rechnen und Schaltnetze

COMPILER & CODE ANALYSE. Eine Einführung in die Code Analyse auf Grundlage von Compilern und deren Optimierung. 1

HC680 PROGRAMMER'S REFERENCE MANUAL

2. Rechnerarchitektur 2.1 einfache Computer

Die Programmiersprache C

Fehlerkorrektur Bild Demoprozessor

Die Befehle mit dem Ziel IP sind nichts anderes als Sprungbefehle, sie sind unten noch mal aufgeführt.

Technische Informatik 2: Addressierung und Befehle

Zuschauer beim Berlin-Marathon

Computerarithmetik ( )

Debuggen mit GDB (Gnu DeBugger) unter Eclipse

Besprechung des 3. Übungsblattes MIMA-Interpreter MIMA-Aufgabe: Primzahltest Weitere MIMA-Aufgaben online

Interrupts. Funktionsprinzip. Funktionsprinzip. Beispiel in C

Kapitel VI. Speicherverwaltung. Speicherverwaltung

b) Gegeben sei folgende Enumeration: enum SPRACHE {Deutsch, Englisch, Russisch};

Assembler-Programmierung

Midterm-Klausur Technische Grundlagen der Informatik

Erwin Grüner

Unterprogramme, Pointer und die Übergabe von Arrays

0 C (Carry) Überlauf des 8ten Bits. 1 DC (Digit Carry) Überlauf des 4ten Bits. Mnemonic Parameter Beschreibung Status-Flags.

lldeckblatt Migration von AWL-Programmen nach S STEP 7 (TIA Portal) V12 FAQ Januar 2013 Service & Support Answers for industry.

Kap 4. 4 Die Mikroprogrammebene eines Rechners

3 Arithmetische Schaltungen

4D Server v12 64-bit Version BETA VERSION

5. Unterprogrammtechnik/Module

Informatik. Studiengang Chemische Technologie. Michael Roth WS 2012/2013. Hochschule Darmstadt -Fachbereich Informatik-

Virtueller Speicher. SS 2012 Grundlagen der Rechnerarchitektur Speicher 44

CA Übung Christian kann heute nicht kommen => ich bin heute da, Christian das nächste Mal wieder

1.7 Assembler Programmierung

Compiler: Vom Code zum Maschinen-Code. C Programmierung - Vorlesung 2 Hochschule Regensburg Universitätsstraße 31, Regensburg

1. Aktionen-Palette durch "Fenster /Aktionen ALT+F9" öffnen. 2. Anlegen eines neuen Set über "Neues Set..." (über das kleine Dreieck zu erreichen)

2. Darstellung von Information im Computer

2.2 Rechnerorganisation: Aufbau und Funktionsweise

Der MS-DOS Standardmonitor und Debugger DEBUG

Eine Einführung in C-Funktionen

q) Geben Sie Befehle an, die ein neues globales Register anlegen und dieses mit Speicheradresse 0x initialisieren,

Technische Informatik 1

PIWIN 1 Übung Blatt 5

Name: ES2 Klausur Thema: ARM Name: Punkte: Note:

Sage 200 BI Installationsanleitung Cubes & Datawarehouses Manuelle Installation ohne SRSS/Sage Cockpit. Version

DATEN UND BEFEHLSFORMATE, ADDRESSIERUNGSARTEN UND MASCHINEN- PROGRAMMIERUNGSKONZEPTE

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

Speicher Virtuelle Speicherverwaltung. Speicherverwaltung

Programmierung 2. Übersetzer: Code-Erzeugung. Sebastian Hack. Klaas Boesche. Sommersemester

DOKUMENTATION VOGELZUCHT 2015 PLUS

Instruktionssatz-Architektur

Dokumentation. juris Autologon-Tool. Version 3.1

Migration anhand von Wordpress

Javakurs für Anfänger

Einführung in die technische Informatik

Mikroprozessor als universeller digitaler Baustein

1 Einleitung zum RISC Prozessor

Vorkurs C++ Programmierung

Sucosoft S40 KOP/FBS KOP FBS

JMPCN Sprungbefehl nur ausführen, wenn VKE 0 ist. JMPC Sprungbefehl nur ausführen, wenn VKE 1 ist. JMP Ohne Bedingung zur Sprungmarke wechseln.

Die Bedeutung abstrakter Datentypen in der objektorientierten Programmierung. Klaus Kusche, September 2014

Grundpraktikum Netz- und Datensicherheit. Thema: Buffer Overflow Angriffe, Teil 2

L3. Datenmanipulation

Einheit Variablen in der Programmiersprache C Variablen-Modell, Variablen-Vereinbarungen

VB.net Programmierung und Beispielprogramm für GSV

1 Aufgaben zu Wie funktioniert ein Computer?

Aufgabenkatalog. Computersysteme 1 Dr. Michael Zwick. Technische Universität München

Java Einführung Methoden in Klassen

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Betriebssysteme Kap B: Hardwaremechanismen

GCM 100 GRAF-SYTECO H019A00. SYsteme TEchnischer COmmunication anzeigen, bedienen, melden, steuern, visualisieren und zählen

Programmierung in C. Grundlagen. Stefan Kallerhoff

C++ Grundlagen. ++ bedeutet Erweiterung zum Ansi C Standard. Hier wird eine Funktion eingeleitet

Kode-Erzeugung, Abstrakte Maschinen, Rechnerarchitekturen

Send/Receive PCU/MCU. Protokoll

Einführung in VisualBasic for Applications. Stefan Mahlitz

Transkript:

6.5 MMIX Befehle 291 Aufrufkonventionen Eine Aufrufkonvention (engl. calling convention) legt fest, wie einer Funktion Parameter übergeben werden und wie der Rückgabewert zurückgegeben wird. Damit spezifiziert eine Aufrufkonvention u.a. Antworten auf Fragen wie: Werden alle Parameter auf dem Stack übergeben oder werden die ersten n Parameter in Registern übergeben und die restlichen auf dem Stack? Welche Register werden zur Parameterübergabe verwendet? In welcher Reihenfolge werden die Parameter auf dem Stack bzw. in den Registern abgelegt? Werden Gleitkommazahlen in anderen Registern übergeben als Festkommazahlen? In welchen? Wer bereinigt den Stack: Der Funktionsaufrufer oder die Funktion? Wie wird der Rückgabewert zurückgegeben: Auf dem Stack oder in einem Register? In welchem? Da unterschiedliche Prozessorarchitekturen unterschiedliche Register haben (Anzahl, Funktion,...) und sich auch bezüglich der Verwendung des Stacks unterscheiden können, sind Aufrufkonventionen architekturabhängig. Funktionen können auf einer Prozessorarchitektur in vielfältiger Art und Weise aufgerufen werden. Somit gibt es für jede Prozessorarchitektur in der Regel auch mehrere mögliche Aufrufkonventionen. Bei der Programmierung in Hochsprache ist das Einhalten der gewünschten Aufrufkonvention Aufgabe des Compilers. Parameterübergabe auf dem Stack beim MMIX Der Stack ist ein Bereich im Speicher des Prozessors, in dem Funktionsparameter, Rücksprungadressen und lokale Variable nacheinander aufgerufender Funktionen aufeinandergestapelt (engl. stack = Stapel) werden. Beim MMIX kann der Stack am Ende des Datensegments aufgebaut werden, beginnend an Adresse 0x3FF...F8 in Richtung niedrigerer Adressen wachsend. Der Stack wird immer über den sog. Stackpointer angesprochen. Der Stackpointer wird realisiert durch ein Register, in dem die Adresse der auf dem Stack ganz oben liegenden Daten abgelegt ist. Viele Prozessoren verwenden ein spezielles Stackpointer-Register. Beim MMIX verwenden wir ein globales Allzweckregister als Stackpointer.

292 6 MMIX-Prozessor Beim MMIX kann die Verwendung eines Stacks wie folgt umgesetzt werden: Beim Start eines Programmes wird mit der Anweisung SP GREG #4000000000000000 ein globales Register angelegt, mit 0x4000000000000000 initialisiert und über die Marke SP angsprechbar gemacht. Über diese Marke wird der Stackpointer dann zukünftig angesprochen. 8 Byte 0x3FFFFFFFFFFFFFF8 SP 0x4000000000000000 Der Stackpointer zeigt jetzt auf den Beginn des Pool-Segments. Beim Aufruf einer Funktion mit n Parametern wird vom aktuellen Wert des Stackpointers n 8 subtrahiert. Der Stackpointer zeigt dann auf eine niedrigere Adresse, d.h. er wandert nach oben. Im Falle n =3wird 3 8 subtrahiert. SUB :SP,:SP,3*8 Der Stackpointer zeigt dann auf Adresse 0x3FFFFFFFFFFFFFE8. SP 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000

6.5 MMIX Befehle 293 Anschließend werden die Parameter mittels Stackpointer auf den Stack kopiert. a,:sp,0 b,:sp,1*8 c,:sp,2*8 SP 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 1. Parameter für Fkt 2. Parameter für Fkt 3. Parameter für Fkt Nachdem die Parameter auf den Stack kopiert sind, wird mit dem GO-Befehl in die Funktion gesprungen. Dazu wird die Einsprungs-Marke der Funktion angegeben, z.b. Fkt. Als Register zur Speicherung der Rücksprungadresse sollte ein Register angegeben werden, das keine Daten enthält, die noch benötigt werden. Es bietet sich an, die Rücksprungadresse immer in demselben Register abzulegen, beispielsweise in Register 0. GO $0,:Fkt

294 6 MMIX-Prozessor Als Aufrufkonvention legen wir fest, dass die aufgerufene Funktion sicherstellen muss, dass sie keine vom Funktionsaufrufer in Registern gespeicherten Daten überschreibt. Da die Funktion die vom Funktionsaufrufer verwendeten Register nicht zwingend kennt (z.b. Bibliotheksfunktion), sichert sie alle von ihr selbst verwendeten Register auf den Stack. Die Funktion kann die Register dann verwenden, muss aber unmittelbar vor dem Rücksprung zum Funktionsaufrufer die alten Werte wieder vom Stack in die entsprechenden Register zurück kopieren. Verwendet die Funktion beispielsweise die Register 1 und 2, so sichert sie diese auf den Stack. SUB :SP,:SP,2*8 $1,:SP,0 $2,:SP,1*8 SP 0x3FFFFFFFFFFFFFD8 0x3FFFFFFFFFFFFFE0 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 Sicherung $1 Fkt Sicherung $2 Fkt 1. Parameter für Fkt 2. Parameter für Fkt 3. Parameter für Fkt Sind die Register auf den Stack gesichert, lädt die Funktion die für sie bestimmten Parameter vom Stack und verarbeitet sie. LDO $1,:SP,2*8 Parameter 1 LDO $2,:SP,3*8 Parameter 2...... LDO $2,:SP,4*8 Parameter 3......

6.5 MMIX Befehle 295 Ruft die Funktion Fkt selbst eine andere Funktion Fkt2 auf, so sichert sie zunächst die Rücksprungadresse auf den Stack, kopiert die der Funktion Fkt2 zu übergebenden Parameter auf den Stack und ruft dann Funktion Fkt2 auf. SUB :SP,:SP,2*8 $0,:SP,1*8 Rücksprungadresse $1,:SP,0 Parameter für Fkt2 GO $0,:Fkt2 SP 0x3FFFFFFFFFFFFFC8 0x3FFFFFFFFFFFFFD0 0x3FFFFFFFFFFFFFD8 0x3FFFFFFFFFFFFFE0 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 Parameter für Fkt2 Sicherung $0 Fkt Sicherung $1 Fkt Sicherung $2 Fkt 1. Parameter für Fkt 2. Parameter für Fkt 3. Parameter für Fkt

296 6 MMIX-Prozessor Die Funktion Fkt2 sichert nun ihrerseits die von ihr verwendeten Register auf den Stack, lädt den ihr übergebenen Parameter vom Stack und führt damit Berechnungen durch. SUB :SP,:SP,2*8 $1,:SP,0 Sicherung $1 $2,:SP,1*8 Sicherung $2 LDO $2,SP,2*8 Parameter laden...... SP 0x3FFFFFFFFFFFFFB8 0x3FFFFFFFFFFFFFC0 0x3FFFFFFFFFFFFFC8 0x3FFFFFFFFFFFFFD0 0x3FFFFFFFFFFFFFD8 0x3FFFFFFFFFFFFFE0 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 Sicherung $1 Fkt 2 Sicherung $2 Fkt 2 Parameter für Fkt2 Sicherung $0 Fkt Sicherung $1 Fkt Sicherung $2 Fkt 1. Parameter für Fkt 2. Parameter für Fkt 3. Parameter für Fkt

6.5 MMIX Befehle 297 Hat Fkt2 ihre Berechnungen abgeschlossen, legt Sie den Rückgabewert an der Stelle auf dem Stack ab, an der ihr der Parameter übergeben wurde. Sind mehrere Parameter übergeben worden, wird der Rückgabewert an die Stelle desjenigen Parameters mit der höchsten Adresse geschrieben. Wurde kein Parameter übergeben, so muss vor der Sicherung der Register auf dem Stack Platz freigehalten werden. $2,:SP,2*8 Rückgabewert SP 0x3FFFFFFFFFFFFFB8 0x3FFFFFFFFFFFFFC0 0x3FFFFFFFFFFFFFC8 0x3FFFFFFFFFFFFFD0 0x3FFFFFFFFFFFFFD8 0x3FFFFFFFFFFFFFE0 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 Sicherung $1 Fkt 2 Sicherung $2 Fkt 2 Rückgabewert von Fkt2 Sicherung $0 Fkt Sicherung $1 Fkt Sicherung $2 Fkt 1. Parameter für Fkt 2. Parameter für Fkt 3. Parameter für Fkt

298 6 MMIX-Prozessor Nach dem Ablegen des Rückgabewerts auf dem Stack muss die Funktion Fkt2 die auf den Stack gesicherten Register wieder herstellen. Anschließend muss der Stackpointer so angepasst werden, dass er auf den Rückgabewert zeigt, so dass er vom Funktionsaufrufer ausgelesen werden kann, ohne die Anzahl der von Fkt2 auf den Stack gesicherten Register zu kennen. Anschließend springt die Funktion Fkt2 zurück zum Funktionsaufrufer. Als Rücksprungadresse dient Register 0 mit dem Offset 0. Für den GO-Befehl muss wieder ein Register zur Speicherung der Rücksprungadresse angegeben werden, auch wenn nicht an das Ende der Funktion Fkt2 zurückgesprungen wird. Da der in Register 0 enthaltene Wert nach dem Rücksprung nicht mehr benötigt wird, kann Register 0 auch wieder zur Abspeicherung dieser Rücksprungadresse verwendet werden (1. Parameter des GO-Befehls). LDO $1,:SP,0 LDO $2,:SP,1*8 ADD :SP,:SP,2*8 GO $0,$0,0 SP 0x3FFFFFFFFFFFFFB8 0x3FFFFFFFFFFFFFC0 0x3FFFFFFFFFFFFFC8 0x3FFFFFFFFFFFFFD0 0x3FFFFFFFFFFFFFD8 0x3FFFFFFFFFFFFFE0 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 Sicherung $1 Fkt 2 Sicherung $2 Fkt 2 Rückgabewert von Fkt2 Sicherung $0 Fkt Sicherung $1 Fkt Sicherung $2 Fkt 1. Parameter für Fkt 2. Parameter für Fkt 3. Parameter für Fkt Auf die Werte oberhalb des Stackpointers wird nicht mehr zugegriffen. Sie werden aber nicht explizit gelöscht/überschrieben.

6.5 MMIX Befehle 299 Die Funktion Fkt kann nun das ihr von Fkt2 übergebene Ergebnis vom Stack auslesen und mit ihren Berechnungen fortfahren. Nach dem Auslesen des Rückgabewerts von Fkt2 addiert die Funktion Fkt noch den Wert 8 zum Stackpointer. Damit zeigt der Stackpointer auf dieselbe Stelle wie vor dem Aufruf von Fkt2. Der Aufruf von Fkt2 ist damit offiziell abgeschlossen. LDO ADD $1,:SP,0 :SP,:SP,8 SP 0x3FFFFFFFFFFFFFB8 0x3FFFFFFFFFFFFFC0 0x3FFFFFFFFFFFFFC8 0x3FFFFFFFFFFFFFD0 0x3FFFFFFFFFFFFFD8 0x3FFFFFFFFFFFFFE0 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 Sicherung $1 Fkt 2 Sicherung $2 Fkt 2 Rückgabewert von Fkt2 Sicherung $0 Fkt Sicherung $1 Fkt Sicherung $2 Fkt 1. Parameter für Fkt 2. Parameter für Fkt 3. Parameter für Fkt

300 6 MMIX-Prozessor Die Funktion Fkt kann nun das Ergebnis von Fkt2 für ihre weiteren Berechnungen verwenden. Hat die Funktion Fkt ihre Berechnungen abgeschlossen, kopiert sie ihren Rückgabewert auf den Stack, stellt die von ihr gesicherten Register wieder her, passt den Stackpointer so an, dass er auf den Rückgabewert zeigt und kehrt schließlich zum Funktionsaufrufer zurück....... $1,:SP,5*8 LDO $0,:SP,0 LDO $1,:SP,1*8 LDO $2,:SP,2*8 ADD :SP,:SP,5*8 GO $0,:$0,0 SP 0x3FFFFFFFFFFFFFB8 0x3FFFFFFFFFFFFFC0 0x3FFFFFFFFFFFFFC8 0x3FFFFFFFFFFFFFD0 0x3FFFFFFFFFFFFFD8 0x3FFFFFFFFFFFFFE0 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 Sicherung $1 Fkt 2 Sicherung $2 Fkt 2 Rückgabewert von Fkt2 Sicherung $0 Fkt Sicherung $1 Fkt Sicherung $2 Fkt 1. Parameter für Fkt 2. Parameter für Fkt Rückgabewert von Fkt

6.5 MMIX Befehle 301 Der Funktionsaufrufer kann nun das Ergebnis der Funktion Fkt über den Stackpointer auslesen und danach den Stackpointer wieder anpassen, so dass er auf die selbe Stelle zeigt wie vor dem Aufruf der Funktion Fkt. LDO ADD $1,:SP,0 :SP,:SP,8 SP 0x3FFFFFFFFFFFFFB8 0x3FFFFFFFFFFFFFC0 0x3FFFFFFFFFFFFFC8 0x3FFFFFFFFFFFFFD0 0x3FFFFFFFFFFFFFD8 0x3FFFFFFFFFFFFFE0 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 Sicherung $1 Fkt 2 Sicherung $2 Fkt 2 Rückgabewert von Fkt2 Sicherung $0 Fkt Sicherung $1 Fkt Sicherung $2 Fkt 1. Parameter für Fkt 2. Parameter für Fkt Rückgabewert von Fkt

302 6 MMIX-Prozessor Aufgaben a) Geben Sie den Befehl an, mit dem Sie den Stackpointer als globales Register anlegen, mit 0x4000000000000000 initialisieren und über die Marke SP ansprechbar machen. SP GREG #4000000000000000 b) Geben Sie die Befehle an, mit denen der Funktionsaufrufer aus dem Namensraum Main: heraus Register 3 und 4 als Parameter auf dem Stack ablegt und danach die global definierte Funktion Str aufruft. Die Rücksprungadresse soll in Register 0 abgelegt werden. SUB GO :SP,:SP,2*8 $3,:SP,0*8 $4,:SP,1*8 $0,:Str c) Geben Sie die Befehle an, mit denen Sie den Namensraum Str: anlegen, dann die Funktion Str beginnen und die Register 0, 1 und 2 auf den Stack sichern. PREFIX Str: :Str SUB :SP,:SP,3*8 $0,:SP,0 $1,:SP,1*8 $2,:SP,2*8

6.5 MMIX Befehle 303 d) Tragen Sie in nachfolgende Abbildung die auf dem Stack gespeicherten Werte ein und geben Sie die Position des Stackpointers an. 0x3FFFFFFFFFFFFFD0 SP 0x3FFFFFFFFFFFFFD8 0x3FFFFFFFFFFFFFE0 0x3FFFFFFFFFFFFFE8 0x3FFFFFFFFFFFFFF0 0x3FFFFFFFFFFFFFF8 0x4000000000000000 Sicherung $0 Sicherung $1 Sicherung $2 2. Parameter 1. Parameter e) Geben Sie die Befehle an, mit denen Sie die übergebenen Parameter in die Register 1 und 2 einlesen. LDO LDO $1,:SP,3*8 $2,:SP,4*8 f) Geben Sie die Befehle an, mit denen Sie den Wert aus Register 1 als Ergebnis auf dem Stack ablegen, die auf den Stack gesicherten Register wieder herstellen, den Stackpointer anpassen und zurück zum Funktionsaufrufer springen. Die Rücksprungadresse steht in Register 0 und soll auch wieder dort abgelegt werden. $1,:SP,4*8 LDO $0,:SP,0 LDO $1,:SP,1*8 LDO $2,:SP,2*8 ADD :SP,:SP,4*8 GO $0,$0,0

304 6 MMIX-Prozessor g) Geben Sie die Befehle an, mit denen Sie den Namensraum Str: wieder beenden. PREFIX : h) Geben Sie die Befehle an, mit denen der Funktionaufrufer das Ergebnis vom Stack in das Register 1 einliest und den Stackpointer anpasst. LDO ADD $1,:SP,0 :SP,:SP,8

6.5 MMIX Befehle 305 T i) Was ist der Stack? Der Stack ist ein Bereich im Arbeitsspeicher der lokale Programmdaten wie lokale Variable, in den Arbeitsspeicher gesicherte Register und Rücksprungadressen enthält. Der englische Begriff Stack bedeutet Stapel und rührt daher, dass die Daten dort gestapelt werden. T j) Wo beginnt der Stack und in welche Richtung wächst er? Der Stack beginnt am Ende des Datensegments und wächst in Richtung kleinerer Adressen. T k) Was ist der Stack-Pointer? Der Stack-Pointer ist ein Register das die Adresse des zuletzt auf dem Stack abgelegten Elements enthält. T l) Wie werden Daten adressiert, die auf dem Stack liegen? Daten auf dem Stack werden immer über den Stack-Pointer adressiert. Der Stack- Pointer dient dabei als Basis-Adresse, auf die ein Offset addiert wird um andere Elemente als das oberste Element des Stacks zu adressieren.

306 6 MMIX-Prozessor T m) Welche Operationen muss man ausführen um die Werte zweier Register (acht Byte breite Datenworte) auf dem Stack abzulegen? Den Wert des Stack-Pointers um 2 8 = 16 verringern Die beiden Datenworte an die Adresse Stack-Pointer und Stack-Pointer +8speichern T n) Wie wird der Stack bei Funktionsaufrufen verwendet? Beim Aufruf der Funktion die Parameter auf dem Stack ablegen. In der Funktion die Rücksprungadresse auf den Stack sichern (push), diejenigen Register, die von der Funktion geändert werden, auf den Stack sichern (push), Parameter vom Stack in die Register einlesen, Parameter verarbeiten um ein Ergebnis zu berechnen, das Ergebnis auf dem Stack ablegen, damit der Funktionsaufrufer es auslesen kann, die zuvor auf den Stack gesicherten Register wiederherstellen (pop), die zuvor auf den Stack gesicherte Rücksprungadresse wieder vom Stack auslesen (pop), den Stackpointer so anpassen, dass er aufs Ergebnis zeigt, zum Funktionsaufrufer zurückspingen. Nach Rückkehr zum Funktionsaufrufer das berechnete Ergebnis vom Stack auslesen (pop).

6.5 MMIX Befehle 307 T o) Geben Sie den Befehl an mit dem Sie für den Stack-Pointer ein globales Register reservieren und dieses mit 0x4000 0000 0000 0000 initialisieren. SP GREG #4000 0000 0000 0000 T p) Warum initialisieren wir den Stack-Pointer mit 0x4000 0000 0000 0000, d.h. mit dem Beginn des Poolsegments, und nicht mit dem Ende des Datensegments? Bevor Daten auf den Stack gesschrieben werden (push), wird der Wert des Stack- Pointers um die Anzahl der zu schreibenden Byte verringert. Wird bspw. ein Octa (64 Bit ) 8 Byte) auf den Stack geschrieben, so wird der Stack-Pointer um 1 8 verringert und zeigt dann auf die Adresse #3FFF FFFF FFFF FFF8. Das ist genau das letzte Octa-Datenwort im Datensegment. T q) Geben Sie die MMIX-Befehle an, mit denen Sie Register $1 und $2 auf den Stack schreiben und dann die Funktion fkt aufrufen. Nehmen Sie an, dass Ihr Code im Namensraum Main: steht und fkt im Namensraum Fkt: unter dem Namen :fkt angelegt wurde. Sichern Sie die Rücksprungadresse in Register 0. SUB GO :SP,:SP,2*8 $1,:SP,0 $2,:SP,1*8 $0,:fkt

308 6 MMIX-Prozessor Nehmen Sie an, dass Sie eine Funktion im Namensraum Fkt: implementieren. T r) Geben Sie die MMIX-Befehle an, mit denen Sie die Register 0, 1, 2 und 3 auf den Stack sichern und anschließend zwei acht Byte breite Parameter vom Stack in die Register 1 und 2 einlesen. SUB LDO LDO :SP,:SP,4*8 $0,:SP,0 $1,:SP,1*8 $2,:SP,2*8 $3,:SP,3*8 $1,:SP,4*8 $2,:SP,5*8 T s) Zeichnen Sie, wie der Stack nach diesen Operationen aussieht. SP! 0x3FFF FFFF FFFF FFD0 $0 0x3FFF FFFF FFFF FFD8 $1 0x3FFF FFFF FFFF FFE0 $2 0x3FFF FFFF FFFF FFE8 $3 0x3FFF FFFF FFFF FFF0 $1 0x3FFF FFFF FFFF FFF8 $2

6.5 MMIX Befehle 309 T t) Im Hauptprogramm wurden die Parameter in die Register 1 und 2 geschrieben. Im Unterprogramm wurden Register 1 und 2 dann auf den Stack gesichert und dann dieselben Werte wieder vom Stack in Register 1 und 2 geladen, obwohl sich die Werte von Register 1 und 2 in der Zwischenzeit nicht geändert hatten. Warum haben wir und diesen Schritt nicht gespart sondern dieselben Werte, die in Registern 1 und 2 waren, nochmal reingeschrieben? Das Unterprogramm hat in der Regel keine Informationen darüber, in welchen Registern der Funktionsaufrufer die Parameter abgelegt hatte, da beispielsweise Funktionsaufrufer und Unterprogramm von unterschiedlichen Personen entwickelt wurden. Wenn man aber die Anzahl und Reihenfolge der Parameter kennt, weiß man, wie man diese vom Stack auslesen muss und kann diese auch ohne Kenntnis der verwendeten Register auslesen. T u) Warum speichert man die Rücksprungadresse auf dem Stack? Falls die aufgerufene Funktion ihrerseits wieder eine Funktion aufruft und dabei das Register, in dem die Rücksprungadresse gespeichert ist, überschreibt, dann würde die Rücksprungadresse verloren gehen. T v) Was würde passieren, wenn der Stack so groß wird, dass er mit den Daten zusammenstößt, die am Beginn des Datensegments liegen? Das Programm würde wahrscheinlich abstürzen, da möglicherweise die Rücksprungadressen überschrieben werden würden und dann zu völlig falschen Speicheradressen verzweigt werden würde.

310 6 MMIX-Prozessor T w) Geben Sie die MMIX-Befehle an, mit denen Sie den Inhalt von Register 3 als Ergebnis auf dem Stack ablegen, dann die Register 0, 1, 2 und 3 wiederherstellen und anschließend zurück zum Funktionsaufrufer springen. $3,:SP,5*8 LDO $0,:SP,0 LDO $1,:SP,1*8 LDO $2,:SP,2*8 LDO $3,:SP,3*8 ADD :SP,:SP,5*8 GO $0,$0,0 T x) Nehmen Sie an, Sie sind wieder im Hauptprogramm. Geben Sie die Befehle an mit denen Sie das Ergebnis der Funktion vom Stack in das Register 1 einlesen. LDO ADD $1,:SP,0 :SP,:SP,8 T y) Warum muss der Stack-Pointer angepasst werden nachdem das Ergebnis vom Stack geladen wurde? Würde man das nicht machen, würde der Stack-Pointer nicht auf die selbe Stelle zeigen wie vor dem Funktionsaufruf. Dadurch hätte man beim Zugriff auf Stack- Inhalte, die vom Stack-Pointer aus gesehen an höheren Adressen liegen, immer einen Versatz, in unserem Beispiel um acht Byte.

6.5 MMIX Befehle 311 Beispielprogramm: Quadratische Gleichung In dieser Übung schreiben Sie ein MMIX Programm zur Lösung der Quadratischen Gleichung a x 2 + b x + c =0mit der Formel x 1,2 = b±p b 2 4 a c 2 a zu lösen. Die Variable a, b und c sind als Festkommazahlen gegeben; das Ergebnis soll als Gleitkommazahl angegeben werden. a) Geben Sie den MMIX Befehl an, mit dem Sie den Stack-Pointer anlegen und über die Marke SP ansprechbar machen. SP GREG #4000000000000000 Zunächst soll das Hauptprogramm implementiert werden. b) Geben Sie den MMIX-Befehl an, mit dem Sie den Namensraum Main: eröffnen. PREFIX Main: c) Reservieren Sie an Adresse 0x2000 0000 0000 0000 die 64 Bit breiten Speicherworte A, B, C, X1 und X2 und initialisieren Sie A mit 2, B mit 4 und C mit 8. LOC #2000 0000 0000 0000 GREG @ A OCTA 2 B OCTA 4 C OCTA 8 X1 OCTA X2 OCTA d) Geben Sie den Befehl an, mit dem Sie Register 1 durch buf ansprechbar machen. buf IS $1

312 6 MMIX-Prozessor e) Beginnen Sie das Hauptprogramm, legen Sie A, B und C auf dem Stack ab und rufen Sie dann die global definierte Funktion QuadGleich auf. Speichern Sie dabei die Rücksprungadresse in Register $0. :Main SUB :SP,:SP,3*8 LDO buf,a buf,:sp,0 LDO buf,b buf,:sp,8 LDO buf,c buf,:sp,2*8 GO $0,:QuadGleich f) Geben Sie den MMIX Code an, mit dem Sie die Ergebnisse x 1 und x 2 der Funktion vom Stack auslesen und im Arbeitsspeicher an den Marken X1 bzw. X2 ablegen. LDO LDO ADD buf,:sp,0 buf,x1 buf,:sp,8 buf,x2 :SP,:SP,2*8 g) Geben Sie die Anweisungen an, mit denen Sie das Programm und den Namensraum Main: beenden. TRAP PREFIX : 0,:Halt,0

6.5 MMIX Befehle 313 Im Folgenden soll die Funktion QuadGleich implementiert werden, von der folgender Programm-Code bereits gegeben ist: PREFIX QuadGleich: a IS $1 b IS $2 c IS $3 x1 IS $4 x2 IS $5 disk IS $6 buf1 IS $7 buf2 IS $8 Der Funktion QuadGleich werden die Parameter a, b und c wie folgt auf dem Stack übergeben: SP! a b c h) Geben Sie an der Marke :QuadGleich die Befehle an, mit denen Sie die verwendeten Register auf den Stack sichern und die Parameter a, b und c dann vom Stack in die Register a, b und c einlesen. :QuadGleich SUB :SP,:SP,8*8 a,:sp,0 LDO LDO LDO b,:sp,8 c,:sp,2*8 x1,:sp,3*8 x2,:sp,4*8 disk,:sp,5*8 buf1,:sp,6*8 buf2,:sp,7*8 a,:sp,8*8 b,:sp,9*8 c,:sp,10*8

314 6 MMIX-Prozessor i) Geben Sie den MMIX-Befehlscode an, der im Fall a =0das Ergebnis x = c/b berechnet, dieses dann sowohl in x1 und x2 speichert und dann an die Marke Speichern springt, und im Fall a 6= 0an die Marke Anicht0 springt. BNZ FLOT NEG FLOT FDIV SET JMP a,anicht0 b,b c,0,c c,c x1,c,b x2,x1 Speichern j) Geben Sie an Marke Anicht0 den MMIX Code an, mit dem Sie die Diskriminante b 2 4 a c mittels Festkomma-Arithmetik berechnen und das Ergebnis in Register disk ablegen. Anicht0 MUL buf1,a,c SLU MUL SUB buf1,buf1,2 buf2,b,b disk,buf2,buf1

6.5 MMIX Befehle 315 k) Geben Sie den MMIX Code an mit dem Sie im Fall disk < 0 an die Marke Dneg verzweigen, im Fall disk =0an die Marke D0 verzweigen und im Fall disk > 0 an die Marke Dpos verzweigen. BN BZ JMP disk,dneg disk,d0 Dpos l) Geben Sie an Marke Dneg den MMIX Code an, mit dem Sie x1 und x2 auf NaN setzen; verzweigen Sie dann an die Marke Speichern. Dneg SET x1,0 SUB x1,x1,1 SET x2,x1 JMP Speichern NaN: Exponent alle Bits gesetzt und f > 0 m) Geben Sie an Marke D0 den MMIX Code an, mit dem Sie b/2a berechnen und das Ergebnis sowohl in x1 als auch in x2 ablegen. Verzweigen Sie danach an die Marke Speichern. D0 NEG buf1,0,b FLOT buf1,buf1 SL buf2,a,1 FLOT buf2,buf2 FDIV x1,buf1,buf2 SET x1,x2 JMP Speichern

316 6 MMIX-Prozessor n) Geben Sie an Marke Dpos die MMIX Befehle an, mit denen Sie x 1 und x 2 gemäß x 1,2 = b±p b 2 4 a c 2 a berechnen und das Ergebnis in x1 und x2 ablegen. Springen Sie dann an die Marke Speichern. Beachten Sie, dass die Diskriminante bereits berechnet wurde und als Festkommazahl in Register disk abgelegt ist. Dpos SL buf2,a,1 FLOT buf2,buf2 NEG buf1,0,b FLOT buf1,buf1 FLOT disk,disk FSQRT disk,disk FADD x1,buf1,disk x1 berechnen FDIV x1,x1,buf2 FSUB x2,buf1,disk x2 berechnen FDIV x2,x2,buf2 JMP Speichern o) Geben Sie an Marke Speichern die MMIX Befehle an, mit denen Sie x1 und x2 auf den Stack sichern, zum Funktionsaufrufer zurückspringen und den Namensraum QuadGleich: beenden. Speichern U x1,:sp,9*8 8 Variable gesichert + U x2,:sp,10*8 3 Param. = 11 => 0..10 ADD :SP,:SP,9*8 die letzten beiden GO $0,$0,0 sind offset 9 und 10 PREFIX :