Vorlesung Programmieren 16 Vom Programm zur Maschine Dr.-Ing. Erik Burger Version 1.0 ARBEITSGRUPPE ARCHITECTURE-DRIVEN REQUIREMENTS ENGINEERING (ARE) INSTITUT FÜR PROGRAMMSTRUKTUREN UND DATENORGANISATION (IPD), KIT-FAKULTÄT FÜR INFORMATIK are.ipd.kit.edu KIT Universität des Landes Baden-Württemberg und nationales Forschungszentrum in der Helmholtz-Gemeinschaft www.kit.edu
Termine Anmeldung zur Abschlussaufgabe: 02. Februar 23. Februar Anmeldung erst möglich, nachdem Übungsschein als bestanden ins Campus-System eingetragen wurde. (Sonst Voraussetzungsfehler) Eintragung der Übungsscheine für dieses Semester erfolgt ab 11. Februar Eine nachträgliche Anmeldung (nach 23. Februar) ist nicht möglich! Abschlussaufgabe 1: Veröffentlichung: Abgabe: 10. Februar 10. März Abschlussaufgabe 2: Veröffentlichung: Abgabe: 24. Februar 24. März 2 Vorlesung Programmieren: Vom Programm zur Maschine Requirements Engineering, Institut für Programmstrukturen und Datenorganisation
Organisatorisches Exportieren Sie bitte nach der Anmeldung die Liste aller angemeldeten Prüfungen als PDF und bewahren Sie diese bis Ende der Bearbeitungszeit der Abschlussaufgaben auf. Die Tutorien finden bis einschließlich statt. 3
Organisatorisches: Programmieren SoSe 2017 Programmieren-Vorlesung findet nächstes Semester nicht statt Tutorien finden nächstes Semester auch nicht statt Der Übungsschein kann trotzdem erworben werden Fünf Übungsblätter 50 % der Gesamtpunkte zum Erwerb des Scheines Präsenzübung findet statt und muss bestanden werden 4
Literaturhinweis Weiterlesen Prof. Dr. Gerhard Goos Vorlesung über Informatik Band 2: Objektorientiertes Programmieren und Algorithmen, Springer Lehrbuch Kapitel 11 Vom Programm zur Maschine 5
Lernziele Studierende verstehen Funktionsweise der Halde (engl. heap) und des Kellerspeichers (engl. stack) und können die Zusammenhänge mit Prozessen in Verbindung setzen. Studierende können den Einsatz der Datenstrukturen bei der Speichereinteilung erläutern. Studierende können den Einsatz der Datenstrukturen bei unterschiedliche Sprüngen im Programmcode erklären. Studierende können die Funktionsweise und den Einsatz der Datenstrukturen beim Methodenaufruf und Verlassen einer Methode erläutern. 6
Überblick Datenstrukturen: Halde und Kellerspeicher Einsatz der Datenstrukturen beim Aufruf einer Methode Speichereinteilung Adressierung des Speichers Verschiedene Arten von Sprüngen Schritte beim Methodenaufruf Schritte beim Verlassen einer Methode 7
Motivation Von der Java-Datei über den plattformunabhängigen Bytecode hin zum plattformabhängigen Maschinencode.java-Datei plattformunabhängig Compiler.class-Datei Bytecode JVM Maschinencode plattformabhängig 8
Halde Halde (engl. heap) ist ein reservierter Speicher zur Speicherung von Elementen zur Laufzeit bei Bedarf Speichern der Daten in einer beliebigen Anordnung Freigabe des allokierten Speichers durch Aufhebung des Referenzierens Beispiel: Java Heap zur Speicherung von Objekten in Java Dateneinteilung in der Halde minheap maxadr Halde 9
Kellerspeicher Kellerspeicher (engl. stack), auch bekannt als Stapelspeicher, ist eine Datenstruktur. Arbeitsweise: Last-In-First-Out (LIFO) Push-Operation: Das neue Objekt wird auf den Keller gelegt (gestapelt) Pop-Operation: Das neueste Objekt vom Keller heruntergenommen Befehlsreihenfolge: Push(A) Push(B) Push(C) Push(D) D=Pop C=Pop B=Pop D C B A 10
Einsatz des Kellerspeichers Ein Kellerspeicher kann dynamisch wachsen und schrumpfen Allokation des Speichers zur Laufzeit Freigabe des allokierten Speichers nach Abarbeitung des Codes Häufiger Einsatz in Prozessoren, Beispiele: Speichern der Rücksprungadresse beim Aufruf eines Unterprogramms Speichern der Rückgabewerte eines Unterprogramms Speichern aller Parameter der aktuell laufenden Programme, Beispiele: geschachtelter Aufruf einer Rekursion geschachtelter Aufruf der Unterprogramme Speichern der lokalen Variablen minvar Dateneinteilung im Keller Pegel Keller 11
Einsatz des Kellerspeichers Ein Kellerspeicher kann dynamisch wachsen und schrumpfen Allokation des Speichers zur Laufzeit Freigabe des allokierten Speichers nach Abarbeitung des Codes Häufiger Einsatz in Prozessoren, Beispiele: Speichern der Rücksprungadresse beim Aufruf eines Unterprogramms Speichern der Rückgabewerte eines Unterprogramms Speichern aller Parameter der aktuell laufenden Programme, Beispiele: geschachtelter Aufruf einer Rekursion geschachtelter Aufruf der Unterprogramme Speichern der lokalen Variablen minvar Dateneinteilung im Keller Pegel Keller 12
Einsatz des Kellerspeichers Ein Kellerspeicher kann dynamisch wachsen und schrumpfen Allokation des Speichers zur Laufzeit Freigabe des allokierten Speichers nach Abarbeitung des Codes Häufiger Einsatz in Prozessoren, Beispiele: Speichern der Rücksprungadresse beim Aufruf eines Unterprogramms Speichern der Rückgabewerte eines Unterprogramms Speichern aller Parameter der aktuell laufenden Programme, Beispiele: geschachtelter Aufruf einer Rekursion geschachtelter Aufruf der Unterprogramme Speichern der lokalen Variablen minvar Dateneinteilung im Keller Pegel Keller 13
Einsatz des Kellerspeichers Ein Kellerspeicher kann dynamisch wachsen und schrumpfen Allokation des Speichers zur Laufzeit Freigabe des allokierten Speichers nach Abarbeitung des Codes Häufiger Einsatz in Prozessoren, Beispiele: Speichern der Rücksprungadresse beim Aufruf eines Unterprogramms Speichern der Rückgabewerte eines Unterprogramms Speichern aller Parameter der aktuell laufenden Programme, Beispiele: geschachtelter Aufruf einer Rekursion geschachtelter Aufruf der Unterprogramme Speichern der lokalen Variablen minvar Dateneinteilung im Keller Keller Pegel 14
Einsatz des Kellerspeichers Ein Kellerspeicher kann dynamisch wachsen und schrumpfen Allokation des Speichers zur Laufzeit Freigabe des allokierten Speichers nach Abarbeitung des Codes Häufiger Einsatz in Prozessoren, Beispiele: Speichern der Rücksprungadresse beim Aufruf eines Unterprogramms Speichern der Rückgabewerte eines Unterprogramms Speichern aller Parameter der aktuell laufenden Programme, Beispiele: geschachtelter Aufruf einer Rekursion geschachtelter Aufruf der Unterprogramme Speichern der lokalen Variablen minvar Dateneinteilung im Keller Keller Pegel 15
Einsatz des Kellerspeichers Ein Kellerspeicher kann dynamisch wachsen und schrumpfen Allokation des Speichers zur Laufzeit Freigabe des allokierten Speichers nach Abarbeitung des Codes Häufiger Einsatz in Prozessoren, Beispiele: Speichern der Rücksprungadresse beim Aufruf eines Unterprogramms Speichern der Rückgabewerte eines Unterprogramms Speichern aller Parameter der aktuell laufenden Programme, Beispiele: geschachtelter Aufruf einer Rekursion geschachtelter Aufruf der Unterprogramme Speichern der lokalen Variablen minvar Dateneinteilung im Keller Keller Pegel 16
Einsatz des Kellerspeichers Ein Kellerspeicher kann dynamisch wachsen und schrumpfen Allokation des Speichers zur Laufzeit Freigabe des allokierten Speichers nach Abarbeitung des Codes Häufiger Einsatz in Prozessoren, Beispiele: Speichern der Rücksprungadresse beim Aufruf eines Unterprogramms Speichern der Rückgabewerte eines Unterprogramms Speichern aller Parameter der aktuell laufenden Programme, Beispiele: geschachtelter Aufruf einer Rekursion geschachtelter Aufruf der Unterprogramme Speichern der lokalen Variablen minvar Dateneinteilung im Keller Keller Pegel 17
Einsatz des Kellerspeichers Ein Kellerspeicher kann dynamisch wachsen und schrumpfen Allokation des Speichers zur Laufzeit Freigabe des allokierten Speichers nach Abarbeitung des Codes Häufiger Einsatz in Prozessoren, Beispiele: Speichern der Rücksprungadresse beim Aufruf eines Unterprogramms Speichern der Rückgabewerte eines Unterprogramms Speichern aller Parameter der aktuell laufenden Programme, Beispiele: geschachtelter Aufruf einer Rekursion geschachtelter Aufruf der Unterprogramme Speichern der lokalen Variablen minvar Dateneinteilung im Keller Keller Pegel 18
Speichereinteilung Ein Speicher mit dem Adressraum = [0, maxadr]. Die Elemente des Speichers Speicher[i] heißen Speicherzellen Der Wert einer Speicherzelle oder einer Variable heißt Inhalt Der Speicher des Programms besteht aus: Programmbereich für Befehle Kontantenbereich für alle Literale des Programms Datenbereich für alle Variablen 0 maxprog Speichereinteilung Programm maxlit mindat Konstanten Daten maxadr 19
Einteilung des Datenbereichs Grund der Aufteilung des Speichers: Anzahl der Referenzobjekte a priori nicht bekannt Keller wächst nach unten 0 maxprog maxlit mindat Speichereinteilung Programm Konstanten minvar Pegel Dateneinteilung Programmvariable Keller für dynamische Variablen (mit unbeschränkter Lebensdauer) maxadr Daten minheap maxadr Halde Halde für anonyme Objekte (mit unbekannter Lebensdauer) 20
Sprünge Die Variable Befehlszähler (BZ) gehört nicht zum Speicher enthält während der Ausführung die des nächsten auszuführenden Befehls Der Wert der Variable BZ wird bei sequentieller Ausführung der Befehle jedes Mal um 1 erhöht entspricht der des Befehls b markiert mit M, falls das Programm mit Ausführung des Befehls b fortgesetzt wird (Schreibweise goto M). Eine Zuweisung an BZ wird als Sprung bezeichnet und M als Sprungziel 21
Sprünge Im Folgenden beispielhaft drei Formen von Sprüngen: Unbedingte Sprünge (goto M) Beispiel goto BZ±i bedeutet BZ:=BZ±i Bedingte Sprünge (if-then goto M) Interprogrammsprung (gosub M) entspricht dem Aufruf parameterloser Methoden notiert zu BZ:=M auch vor dem Sprung in einer Variable Rückkehradresse:=BZ alt +1. Relative : an M steht der Sprungbefehl goto M die relative kann man als i=m-m berechnen dann entspricht goto M dem Befehl goto BZ+i 22
Bedingte Sprünge - Verzweigung if M(a 1 ) = M(a 2 ) then S end U if: LDV a 1 EQL a 2 NOT then: S end: U JMN end LDV a: Lade a in den Akkumulator EQL a: Vergleiche den Inhalt des Akkumulators mit a NOT: Negiere den Inhalt des Akkumulators JMN a: Bedingter Sprung Grundbegriffe der Informatik, 5.ÜB, Thomas Worsch und Simon Wacker 23
Bedingte Sprünge - Verzweigung if M(a 1 ) = M(a 2 ) then S else T end U if: LDV a 1 EQL a 2 JMN then else: T JMP end then: S end: U LDV a: Lade a in den Akkumulator EQL a: Vergleiche den Inhalt des Akkumulators mit a NOT: Negiere den Inhalt des Akkumulators JMN a: Bedingter Sprung JMP a: Unbedingter Sprung Grundbegriffe der Informatik, 5.ÜB, Thomas Worsch und Simon Wacker 24
Kopfgesteuerte Schleife while M(a 1 ) = M(a 2 ) do S end T while: LDV a 1 EQL a 2 NOT JMN end do: S JMP while end: T LDV a: Lade a in den Akkumulator EQL a: Vergleiche den Inhalt des Akkumulators mit a NOT: Negiere den Inhalt des Akkumulators JMN a: Bedingter Sprung JMP a: Unbedingter Sprung Grundbegriffe der Informatik, 5.ÜB, Thomas Worsch und Simon Wacker 25
Adressierung durch 3 Basisadressen minvar: die Anfangsadresse des Speicherbereichs statischer Programmvariablen Umgebungszeiger (umg): Die Basisadresse für die dynamischen Variablen (lokale Variablen) in der Schachtel des laufenden Unterprogramms Pegel: Kellerpegel des obersten Elementes im Laufzeitkeller Basisadresse für Zwischenergebnisse wird bei jedem Unterprogrammaufruf um 1 erhöht minvar Dateneinteilung Programmvariable einer statischen Variable v mit einer relativen r v Pegel minheap minvar + r v dynamischen Variable v mit einer relativen r v Halde umg + r v maxadr 26
Laufzeitkeller Zur Speicherung dynamischer Programmvariablen Grund für Kellerspeicher: Geschachtelte Unterprogrammaufrufe Kellerspeicher besteht daher aus Einheiten, bekannt als Schachteln (engl. stack frame, activation record) Unterste Schachtel reserviert für statische Variablen Schachtel beinhaltet: lokale Variablen Rückkehradresse etc. minvar Pegel minheap Dateneinteilung Programmvariable maxadr Halde 27
Laufzeitkeller Schachtel Anlegen einer neuen Schachtel beim Aufruf eines Unterprogramms Löschen einer Schachtel beim Verlassen des Unterprogramms Umgebungszeiger umg Kellerpegel Parameter Rückkehradresse Lokale Variable Parameter Rückkehradresse Lokale Variable Schachtel Aufrufer Schachtel Unterprogramm 28
Schritte beim Aufruf einer Methode 1. Erhöhung des Kellerpegels um den Umfang der Schachtel 2. Zuweisung der Werte der aktuellen Parameter in die Schachtel 3. Eintrag der Rückkehradresse in die Schachtel 4. Setzen des Umgebungszeigers auf die Schachtel 5. Methodenaufruf: Sprung auf die erste der Methode 29
Schritte beim Aufruf einer Methode 1. Erhöhung des Kellerpegels um den Umfang der Schachtel 2. Zuweisung der Werte der aktuellen Parameter in die Schachtel 3. Eintrag der Rückkehradresse in die Schachtel 4. Setzen des Umgebungszeigers auf die Schachtel 5. Methodenaufruf: Sprung auf die erste der Methode minvar Pegel Dateneinteilung Programmvariable minheap 30
Schritte beim Aufruf einer Methode 1. Erhöhung des Kellerpegels um den Umfang der Schachtel 2. Zuweisung der Werte der aktuellen Parameter in die Schachtel 3. Eintrag der Rückkehradresse in die Schachtel 4. Setzen des Umgebungszeigers auf die Schachtel 5. Methodenaufruf: Sprung auf die erste der Methode minvar Dateneinteilung Programmvariable Pegel minheap 31
Schritte beim Aufruf einer Methode 1. Erhöhung des Kellerpegels um den Umfang der Schachtel 2. Zuweisung der Werte der aktuellen Parameter in die Schachtel 3. Eintrag der Rückkehradresse in die Schachtel 4. Setzen des Umgebungszeigers auf die Schachtel 5. Methodenaufruf: Sprung auf die erste der Methode minvar Dateneinteilung Programmvariable Parameter Pegel minheap 32
Schritte beim Aufruf einer Methode 1. Erhöhung des Kellerpegels um den Umfang der Schachtel 2. Zuweisung der Werte der aktuellen Parameter in die Schachtel 3. Eintrag der Rückkehradresse in die Schachtel 4. Setzen des Umgebungszeigers auf die Schachtel 5. Methodenaufruf: Sprung auf die erste der Methode minvar Dateneinteilung Programmvariable Parameter Pegel minheap 33
Schritte beim Aufruf einer Methode 1. Erhöhung des Kellerpegels um den Umfang der Schachtel 2. Zuweisung der Werte der aktuellen Parameter in die Schachtel 3. Eintrag der Rückkehradresse in die Schachtel 4. Setzen des Umgebungszeigers auf die Schachtel 5. Methodenaufruf: Sprung auf die erste der Methode minvar Dateneinteilung Programmvariable Pegel minheap Parameter Rückkehradresse 34
Schritte beim Aufruf einer Methode 1. Erhöhung des Kellerpegels um den Umfang der Schachtel 2. Zuweisung der Werte der aktuellen Parameter in die Schachtel 3. Eintrag der Rückkehradresse in die Schachtel 4. Setzen des Umgebungszeigers auf die Schachtel 5. Methodenaufruf: Sprung auf die erste der Methode minvar Dateneinteilung Programmvariable Parameter Rückkehradresse Pegel Lokale Variable minheap 35
Schritte beim Aufruf einer Methode 1. Erhöhung des Kellerpegels um den Umfang der Schachtel 2. Zuweisung der Werte der aktuellen Parameter in die Schachtel 3. Eintrag der Rückkehradresse in die Schachtel 4. Setzen des Umgebungszeigers auf die Schachtel 5. Methodenaufruf: Sprung auf die erste der Methode minvar Dateneinteilung Programmvariable umg Parameter Rückkehradresse Pegel Lokale Variable minheap 36
Schritte beim Verlassen der Methode 1. Zuweisung eines eventuellen Ergebnisses 2. Zuweisung der Rückkehradresse an ein Register R 3. Rücksetzen des Umgebungszeigers 4. Erniedrigung des Kellerpegels zum Aufbau des Kellers 5. Unbedingter Sprung goto <R> auf die Rückkehradresse Kellerpegel Parameter Rückkehradresse Lokale Variable Parameter Rückkehradresse Lokale Variable Schachtel Aufrufer Schachtel Untermethode 37
Schritte beim Verlassen der Methode 1. Zuweisung eines eventuellen Ergebnisses 2. Zuweisung der Rückkehradresse an ein Register R 3. Rücksetzen des Umgebungszeigers 4. Erniedrigung des Kellerpegels zum Aufbau des Kellers 5. Unbedingter Sprung goto <R> auf die Rückkehradresse Umgebungszeiger umg Kellerpegel Parameter Rückkehradresse Lokale Variable Parameter Rückkehradresse Lokale Variable Schachtel Aufrufer Schachtel Untermethode 39
Schritte beim Verlassen der Methode 1. Zuweisung eines eventuellen Ergebnisses 2. Zuweisung der Rückkehradresse an ein Register R 3. Rücksetzen des Umgebungszeigers 4. Erniedrigung des Kellerpegels zum Aufbau des Kellers 5. Unbedingter Sprung goto <R> auf die Rückkehradresse Kellerpegel Umgebungszeiger umg Parameter Rückkehradresse Lokale Variable Parameter Rückkehradresse Lokale Variable Schachtel Aufrufer Schachtel Untermethode 40
Schritte beim Verlassen der Methode 1. Zuweisung eines eventuellen Ergebnisses 2. Zuweisung der Rückkehradresse an ein Register R 3. Rücksetzen des Umgebungszeigers 4. Erniedrigung des Kellerpegels zum Aufbau des Kellers 5. Unbedingter Sprung goto <R> auf die Rückkehradresse Umgebungszeiger umg Kellerpegel Parameter Rückkehradresse Lokale Variable Parameter Rückkehradresse Lokale Variable Schachtel Aufrufer Schachtel Untermethode 41
Zusammenfassung Halde (engl. Heap) ist ein reservierter Speicher zur Speicherung von Elementen zur Laufzeit bei Bedarf in beliebiger Reihenfolge Kellerspeicher ist eine Datenstruktur nach Last-In-First-Out-Prinzip Allokation des Speichers zur Laufzeit Freigabe des allokierten Speichers nach Abarbeitung des Codes Häufiger Einsatz in Prozessoren Der Speicher des Programms besteht aus: Programmbereich für Befehle Konstantenbereich für alle Literale des Programms Datenbereich für alle Variablen Drei Formen von Sprüngen: Unbedingte Sprünge (goto M) Bedingte Sprünge (if-then goto M) Interprogrammsprung (entspricht dem Aufruf parameterloser Methoden) Aufruf einer Methode vs. Verlassen einer Methode 42