Grundlagen der Informatik III

Transcription

Grundlagen der Informatik III
Grundlagen der Informatik III
WS 2008 / 2009
[Folien basierend auf VL von Prof. Dr. Claudia Eckert,
WS 07/08]
Prof. Dr. rer. nat. Frederik Armknecht
Sascha Müller
Daniel Mäurer
Fachbereich Informatik / CASED
Mornewegstraße 30
64293 Darmstadt
Gliederung der Vorlesung GdI 3
1. Einführung
2. Assemblerprogrammierung
3. Leistungsbewertung
4. Speicherhierarchie
5. Assembler, Binder, Lader
6. Betriebssysteme und Ein-/Ausgabe (Grundlagen)
7. Rechnernetze (Grundlagen)
8. Compiler (Grundlagen)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 2
Gliederung dieses Kapitels
2.1 Instruktionssatz
2.2 Variablen und Register
2.3 Speicherorganisation
2.4 Speicherbefehle
2.5 Befehlsformate
2.6 Konzept der universellen Interpretierbarkeit
2.7 Übersetzung von Kontrollstrukturen
2.8 Verarbeitung von Zeichen
2.9 Höhere Kontrollstrukturen: Prozeduren
2.10 Adressierung
2.11 Fazit
Ziel: systemnahes Programmieren auf der Assemblerebene unter Nutzung des
MARS-Simulators für die MIPS-RISC-Architektur
Achtung: Vorlesung ist kein Assemblerkurs; sie erläutert wichtige Prinzipien.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 3
Kapitel 2 Assemblerprogrammierung
2.1 Instruktionssatz (Befehlssatz, instruction set):
• Maschinen-Sprache zur Beschreibung der einzelnen
Aktionen, die ein Prozessor ausführen kann
• so einfach wie möglich gehalten, primitive Sprache
Beispiel in Vorlesung:
• MIPS-R2000-Instruktionssatz
• einfach, bietet alle wichtigen Konzepte
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 4
Instruktionssatz:
Schnittstelle (Interface) zwischen Compiler und Rechner
High-level
language
program
(in C)
swap(int v[], int k)
{int temp;
temp = v[k];
v[k] = v[k+1];
v[k+1] = temp;
}
Ccompiler
Assembly
language
program
(for MIPS)
swap:
muli $2, $5,4
add $2, $4,$2
lw $15, 0($2)
lw $16, 4($2)
sw $16, 0($2)
sw $15, 4($2)
jr $31
Assembler
Binary machine
language
program
(for MIPS)
00000000101000010000000000011000
00000000100011100001100000100001
10001100011000100000000000000000
10001100111100100000000000000100
10101100111100100000000000000000
10101100011000100000000000000100
00000011111000000000000000001000
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 5
MIPS-Arithmetik: Erstes Beispiel
„ Addiere die Werte der beiden Variablen ‘b‘ und ‘c‘
und weise das Ergebnis der Variablen ‘a‘ zu “
add a, b, c
Assemblerbefehle (instructions) stark formalisiert:
• alle Arithmetikbefehle haben genau 3 Variablen:
Zwei Argumente und einen Ergebnisoperanden
• feste Reihenfolge der Variablen (Ergebnis zuerst)
• jede Zeile ein Befehl
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 6
Pseudobefehle
 Maschinensprache umfasst normalerweise nur eine kleine Anzahl an
möglichen Instruktionen
 Manche Operationen sind nicht direkt implementiert, sondern müssen
durch andere realisiert werden.
 Einige Assembler unterstützen sogenannte Pseudobefehle. Dies sind
Befehle, die es in der Maschinensprache nicht gibt, aber häufig
gebraucht werden.
 Der Assembler übersetzt diese dann in eine geeignete Sequenz von
„echten“ Assemblerbefehlen.
 Aus didaktischen Gründen werden wir im Folgenden gelegentlich
Pseudobefehle verwenden. Diese sind mit eckigen Klammern markiert.
 Mehr dazu später …
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 7
Übersetzung einfacher C-Programme
C
MIPS-Assembler
a = b + c;
add a, b, c
d = a - e;
sub d, a, e
... oder etwas komplizierter:
f=(g+h)–(i+j)
temporäre Variable
add t0, g, h
add t1, i, j
sub f, t0, t1
Beachten von Operator-Prioritäten ( Reihenfolge)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 8
2.2 Variablen und Register
Variablen
• Unterschied zu höheren Programmiersprachen:
Operanden müssen auf begrenzte Anzahl elementarer
Speichereinheiten („Register“) des Prozessors abgebildet werden.
Register:
• Register sind Teile der Programmierer-Schnittstelle
• direkt vom Programm aus zugreifbar
• besitzen eine feste, identische Länge (Wortbreite),
• derzeit typischerweise noch 32 bit (künftig 64 bit)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 9
2.2 Variablen und Register
MIPS-Architektur besitzt
• 32 Register mit je 32 bit,
• Register mit spezieller Funktion:
• Register 0 und 31
• frei benutzbare Register:
• Register 1, 2, ..., 30
• Register besitzen symbolische Namen:
• Benennung: $ <name>
Patterson/Hennessy: Benennung der Register entsprechend der
Nutzung im GNU C Compiler
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 10
MIPS GNU C Registerbenutzung
Name
Nr.
Funktion
$zero
0
der konstante Wert 0
$at
1
reserviert für Assembler
$v0, $v1
2, 3
Resultatwerte und Auswertung von
Gesichert?
bleibt
Ausdrücken
nein
$a0 ... $a3
4-7
Argumente
nein
$t0 ... $t7
8-15
Zwischenwerte (temporär)
nein
$s0 ... $s7
16-23
gesichert (saved)
ja
Beispiel für Nutzung: add $t0, $s2, $t0
addiere Inhalte der Register $t0 und $s2 und speichere das Ergebnis in Register $t0 ab
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 11
MIPS GNU C Registerbenutzung
Name
Nr.
Funktion
Gesichert?
$t8 ... $t9
24-25
weitere Zwischenwerte
$k0, $k1
26, 27 Betriebssystem (OS kernel)
$gp
28
globaler Zeiger (global pointer)
$sp
29
Zeiger auf Kellerspeicher (stack pointer) ja
$fp
30
Rahmenzeiger (frame pointer)
ja
$ra
31
Rücksprungadresse (return address)
ja
(vgl. Patterson/Hennessy, Seite A-24, Figure A.6.1)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 12
nein
ja
Das Beispiel mit Registern
add t0, g, h
add t1, i, j
sub f, t0, t1
f=(g+h)–(i+j)
add $t0, $s1, $s2
add $t1, $s3, $s4
sub $s0, $t0, $t1
Die Variablen der C-Anweisung wurden der Reihe nach den
Registern $s0 - $s4 zugeordnet.
Aber: Wie kommen die Variablenwerte in die Register?
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 13
Register versus Speicher
Problem: Arithmetische Instruktionsoperanden müssen Register sein —
nur 32 Register verfügbar
• Übersetzer weist den Variablen Register zu
• Was aber bei Programmen mit vielen Variablen ?
• d.h. Datenstrukturen müssen im Speicher gehalten werden: wo, wie?
Und wie kommen sie in Register?
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 14
2.3 Speicherorganisation
Antwort: Ablage im Speicher, Zugriff über Adresse,
Load/Store Befehle im Assembler
2.3.1 Byte-Adressierung
Speicher: sehr großes, eindimensionales Bit-Feld
• Elemente des Feldes sind über Adressen
identifizierbar
• Eine Speicheradresse ist als ein Index in das
Feld zu interpretieren
• „Byte Adressierung“ bedeutet, der Index zeigt
auf ein Byte (=8 Bit)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 15
2.3.2 Worte
 Byte: relativ kleine Einheit
 Zur einfacheren Handhabung: größere Einheiten, die „Worte“, häufig:
1 word = 32 Bit (4 Byte)
 MIPS-Befehlssatz: jedes Wort besteht aus 4 Byte
• Ein Register enthält 32 Bit an Daten
• Mit dem Inhalt eines 32-bit Registers lassen sich 232
Byte mit Byte-Adressen von 0 bis 232–1 adressieren
• 230 Worte mit Byte-Adressen 0, 4, 8, ... 232–4
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 16
2.3.2 Worte
 Worte sind sequentiell abgelegt und dürfen nur an Adressen beginnen,
die durch die Wortgröße teilbar sind: diese Eigenschaft heißt Alignment
 Dadurch erreicht man effizientere Speicherzugriffe: pro Wort ist nur eine
Adressberechnung erforderlich
Ausnutzen dieser Organisation:
• z.B. bei der Verarbeitung von Feldern
• Array-Elemente werden sequentiell abgelegt
• Ein Register z.B. $s3 enthält die Anfangsadresse (Basisadresse)
• Element-Adresse A[i]: i-tes Element des Feldes A:
Basisadresse + 4* i
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 17
2.3.3 Byte-Order
Big Endian:
 das Byte mit höchstwertigsten Bits wird zuerst gespeichert, d.h. an der
kleinsten Speicheradresse.
Little-Endian
 das Byte mit niederwertigsten Bits wird zuerst gespeichert
 Beispiel aus dem täglichen Leben: Datumsformat
 yyyy-mm-dd : Big Endian
 dd-mm-yyyy : Little Endian
Bem.: MIPS kennt Big- und Little Endian Order
 MARS-Simulator: arbeitet mit Little Endian
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 18
2.4 MIPS Speicherbefehle: Lade und Speichere
 lw: load word (lade Wort),
 sw: save word (speichere Wort)
 Beispiel:
C:
A[8] = h + A[8]
MIPS: lw $t0, 32($s3) ($s3 enthalt Startadresse von A)
add $t0, $s2, $t0
sw $t0, 32($s3)
 bei sw Zieladresse am Schluss
 Arithmetikoperanden müssen Register, können nicht Speicheradressen
sein!
 MIPS-Adressierungsmodus: Konstante (Basisregister):

Adresse = Konstante + Inhalt des Basisregisters
 z.B. 32($s3) = Offset/Index (32) + Basis-(Index-)Register ($s3)
 lw und sw einzige Befehlstypen, die auf Speicher zugreifen!
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 19
2.4 MIPS Speicherbefehle (Beispiel 1)


Beispiel:
C:
int V[6];
a = V[2]; V[4] = a;
MIPS:
$s1: Basisadresse von V
$s0: a
Ladebefehl: Datenübertragung Speicher  Register
lw $s0, 8($s1)

Speicherbefehl: Datenübertragung Register  Speicher
sw $s0, 16($s1)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 20
2.4 MIPS Speicherbefehle (Beispiel 2)
swap(int v[], int k);
Wert von k steht in Register $5
{int temp;
Startwert von v steht in Register $4
temp = v[k]
v[k] = v[k+1]
Erinnerung: Befehle in eckigen Klammern
v[k+1]= temp;
bezeichnen Pseudobefehle
}
swap:
[mul $2, $5, 4] # $2 = k*4
Adressberechnung
von v[k]
add $2, $4, $2 # $2 = v + k*4
lw $16, 0($2) # lade Inhalt von v[k]
lw $17, 4($2) # lade Inhalt v[k+1]
Datentransport
sw $17, 0($2) # v[k] = v[k+1]
sw $16, 4($2)
Rücksprung
jr $31 # fahre beim Aufrufer fort
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 21
2.4 C-Programme mit variablen Array-Indizes

Beispiel:
C:
MIPS Registerzuweisung:

g = h + A[i]
$s1:
$s2:
$s3:
$s4:
g
h
Basis von A
i
Index auf Speicheradressen abbilden (mit 4 multiplizieren):
mul: Normale Multiplikation
(effizienter) sll: Shift 2 Stellen nach links
[mul $2, $5, 4]
sll $t1, $s4, 2

Wortadresse zu Basisadresse addieren
add $t1, $t1, $s3

Array-Element laden (Adresse von A(i) in $t1)
lw $t0, 0($t1)

Addition ausführen
add $s1, $s2, $t0
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 22
2.4 Zwischenbilanz
MIPS
 Laden von Worten, Adressieren von Bytes
 Arithmetik nur auf Registern
Instruktionen
Bedeutung
add $s1, $s2, $s3
$s1 = $s2 + $s3
sub $s1, $s2, $s3
lw $s1, 100($s2)
sw $s1, 100($s2)
$s1 = $s2 - $s3
$s1 = Memory[$s2+100]
Memory[$s2+100] = $s1
und auch bereits: Immediate Befehle, Shift
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 23
2.5 MIPS Befehlsformate
Background
• Auch Instruktionen sind 32 Bits lang
• Beispiel: Repräsentation eines Additionsbefehls
• Beispiel: MIPS-Assembler: add $t0, $s1, $s2
• Jedes Register hat eigene Nummer:
$t0=8, ..., $t7=15, $s0=16, ..., $s7=23
• Dezimaldarstellung des Additionsbefehls:
0
17
18
Addition
Zielregister
Operandenregister
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 24
8
0
32
hier unbenutzt
2.5 MIPS Befehlsformate
0
17
18
8
0
Addition
Zielregister
Operandenregister
32
hier unbenutzt
In Binärdarstellung:
000000
10001
10010
01000
00000
100000
6 Bit
5 Bit
5 Bit
5 Bit
5 Bit
6 Bit
Beispiel:
10010binär = 1×24 + 0×23 + 0×22 + 1×21 + 0×20 = 18dezl
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 25
2.5.1 MIPS-Befehlsformat „R“ (für Register)
op
rs
rt
rd
shamt
funct
6 Bit
5 Bit
5 Bit
5 Bit
5 Bit
6 Bit
•
•
•
•
•
op: „opcode“; Grundtyp des Befehls (instruction)
rs: erster Operand (Register!)
rt: zweiter Operand (Register!)
rd: Ziel (Register!)
shamt: „shift amount“, für sogenannte Schiebeoperationen wichtig
(siehe später)
• funct: „Funktionscode“; Ergänzung zu op: genaue Spezifikation der
durchzuführenden Operation
Zusammenfassung der MIPS-Architektur bis hierher siehe:
Patterson/Hennessy, Seite 67, Figure 2.7
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 26
2.5.2 MIPS-Befehlsformat „I“ (Immediate)
•
•
•
•
op
rs
rt
adress
6 Bit
5 Bit
5 Bit
16 Bit
op: „opcode“; Grundtyp des Befehls (instruction)
rs: Basisadressregister
rt: Zielregister
adress: Konstante, die Offset bzgl. Basisregister angibt
• lw, sw benötigen 2 Register und 1 Konstante als Array-Offset
• Konstante kann länger als 5 oder 6 Bit sein
• op-Kodierung von lw ist 35 (dezimal) bzw. 100011 (binär)
• op-Kodierung von sw ist 43 (dezimal) bzw. 101011 (binär)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 27
Beispiel
C-Programmtext
A[300] = h + A[300]
Maschinencode dezimal
Maschinencode binär
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 28
MIPS-Assembler
lw $t0, 1200($t1)
add $t0, $s2, $t0
sw $t0, 1200($t1)
2.5.3 MIPS-Befehlsformat „J“ (Jump)
op
adress
6 Bit
26 Bit
• op: „opcode“; Grundtyp des Befehls (instruction)
• adress: Zieladresse
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 29
2.6 Konzept der universellen Interpretierbarkeit
Hintergrund:
• Programme sind gespeicherte Daten
• Befehle sind Bitfolgen bzw. Binärzahlen
Konsequenz:
• Programme werden im Speicher als Maschinencode abgelegt und sie
werden gelesen und geschrieben wie Daten
Speicher
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 30
Speicher für Daten, Programme,
Compiler, Editoren, etc.
2.6.1 Uniforme Verwaltung
Uniforme Verwaltung (Programme, Daten)
keine speziellen Verwaltungsoperationen für Befehlsund Datenspeicher notwendig
Bem:
• Es gibt spezielle Architekturen, die explizit zwischen
Befehls- und Datenspeicher unterscheiden
• welche Vorteile hätte das ggf. doch?
Uniformität
• Speicher ist als uniformer Bit-Container realisiert
• vereinheitlichte, einfache Abläufe,
z.B. Grundzyklus der CPU
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 31
2.6.1 Uniforme Verwaltung
 Grundzyklus der CPU
 Fetch and Execute
• Befehle werden aus dem Speicher geladen (fetch) und in ein spezielles
Register abgelegt
• Die Bits in diesem Register „steuern“ die nachfolgenden Aktionen
(vgl. Kontrollpfad der CPU wie in Technischer Informatik behandelt)
• Befehl wird ausgeführt (execute)
• Holen des „nächsten“ Befehls etc.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 32
2.6.2 Mögliche Probleme
Mögliche Probleme durch universelle Interpretierbarkeit
 kein Schutz der Daten und Programme
 Daten können als Befehle interpretiert werden, auch wenn das so
eigentlich nicht vorgesehen ist
 Beispiel: Buffer-Overflow-Exploits
 Programme können verändert werden und inkorrektes (schädliches)
Verhalten aufweisen
 Beispiel: Schadsoftware: Viren, Trojaner
Lösungsansatz: Aufteilung des Speicherbereichs eines Programms in
Daten und Code-Bereich
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 33
Typisches Speicherlayout eines Programms
0xff…f
Daten
Code
0
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 34
64-bit Adressraum
- 64-bit Adressräume erlauben es, gut 16 Millionen Terabyte Speicher zu
adressieren => immenser Verwaltungsaufwand
-Lösung: Adresse auf weniger Bits reduzieren
-Beispiel (AMD64): Höchstes Bit wird entweder als 0xF..F bzw. als 0x0..0
interpretiert
Bild: Wikipedia
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 35
Bedeutung für die Assemblerprogrammierung
Konzept der Segmentierung
 Trennen in Daten-, Code- (Text) und Stack-Segment
 Datensegment enthält die Daten
 Textsegment den Programmcode
 Stacksegment wird für Prozeduraufrufe benötigt
 dies ist eine übliche Aufteilung des Adressraums
eines Prozesses in heutigen Betriebssystemen
 Frage: woher weiß der Assembler, welche Assemblerbefehle in welches
Segment zu speichern sind?
 Antwort: über Direktiven: .text , .data
 Assembler sortiert dann automatisch
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 36
2.7 Übersetzung von Kontrollstrukturen
 2.7.1 Background: In höheren Programmiersprachen gibt es
programmiersprachliche Konzepte, um die sequentielle Ausführung von
Befehlen zu beeinflussen
 bedingte Programmausführung: u.a.
 if ... then ... [else ...]
 switch ... case ...
 wiederholte Programmausführung: u.a.
 for ...
 while ...
 repeat … until
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 37
2.7.1 Background
 Auf der Maschinenbefehlsebene gibt es keine Befehle, um
Kontrollstrukturen direkt abzubilden
 Es stehen lediglich bedingte und unbedingte Sprungbefehle zur
Verfügung
Sprungbefehle im MIPS-Befehlssatz:
 beq reg1, reg2, label (branch if equal)
 bne reg1, reg2, label (branch if not equal)
 j addr (jump to address), unbedingter Sprung
Problem:
 Die Semantik der Kontrollstrukturen muss mit den Sprungbefehlen
effizient nachgebildet werden
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 38
2.7.2 Übersetzung einfacher Kontrollstrukturen
in Assemblercode
Hier betrachtet: if-then-else, while
IF-Anweisung einer höheren Programmiersprache:
if <bedingung> then <statement1> else <statement2>
Übersetzungsschritte:
 Variablen und Werte, die zur Auswertung der Bedingung benötigt
werden, in Register ablegen
 Beginn der Befehlsfolge <statement2> mit Marke <marke> versehen
 Sprung zu <marke>, falls Bedingung nicht erfüllt
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 39
Beispiel: If .. then .. else Anweisung
C-Programmtext
if (i==j)
f = g + h;
else
f = g - h;
MIPS-Assembler
Testen und Verzweigen
bne $s3, $s4, Else
Addition (im TRUE-Fall)
add $s0, $s1, $s2
Else-Fall überspringen
j Exit
Subtraktion (im FALSE-Fall) Else: sub $s0, $s1, $s2
Ausgang
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 40
Exit:
Beispiel: while Schleife
Schleifen, z.B. while Schleife
While <bedingung> do <statementlist> endwhile
Übersetzungsschritte:
 analog zur If-Anweisung:
Variablen und Werte zur Auswertung der Bedingung werden in Register
geladen
 markiere den ersten Befehl der Statementlist mit einer Marke, z.B. LOOP
 füge als letzten Befehl der Statementliste einen bedingten Sprung zur
Marke LOOP ein
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 41
Weitere Kontrollfluss-Steuerungen
Wie realisiert man einen Vergleich der Art if a < b ?
Neuer Befehl:
Bedeutung:
slt $t0, $s1, $s2
(set on less than)
if $s1 < $s2 then
$t0 = 1
else
$t0 = 0
Damit lässt sich if a < b goto less wie folgt übersetzen:
slt $t0, $s1, $s2
bne $t0, $zero, less
Bem.: Die MIPS-Architektur verwendet ein spezielles Register, das
konstant den Wert „0“ enthält. Es wird in der Assemblersprache als
$zero bezeichnet.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 42
Die MIPS-Architektur bis hierher
Instruktion
Bedeutung
add $s1,$s2,$s3
$s1 = $s2 + $s3
sub $s1,$s2,$s3
$s1 = $s2 – $s3
lw $s1,100($s2)
$s1 = Memory[$s2+100]
sw $s1,100($s2)
Memory[$s2+100] = $s1
bne $s4,$s5,L
nächste Instruktion ist bei L,
wenn $s4 != $s5
beq $s4,$s5,L
nächste Instruktion ist bei L,
wenn $s4 = $s5
slt $t0,$s1,$s2
wenn $s1 < $s2, dann $t0=1,
sonst $t0=0
j Label
nächste Instruktion ist bei Label
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 43
Die MIPS-Architektur bis hierher
add immediate | addi $s1,$s2,100| $s1= $s2+100
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 44
| used to add constants
addi
|
I
|
8 |
18 |
19 |
100
| addi $s1,$s2,100
Quelle: Buch von Patterson/Hennessy, Seite 131, Figure 3.9 (2. A)
R
I
op
op
J
op
rs
rs
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 45
rt
rt
rd
shamt funct
16 Bit Adresse
26 Bit Adresse
Zwischenfazit
Grundprinzipien heutiger Rechnerarchitekturen:
• Instruktionen als (binäre) Zahlen repräsentiert.
• Programme im Speicher abgelegt und können dort
gelesen und geschrieben werden wie Zahlen.
• Dies ist das Prinzip des speicherprogrammierbaren
Rechners (stored program computer)
• Daten und Programme können beliebig im Speicher
angeordnet werden.
• Programme können auch als Daten interpretiert werden (z.B. Compiler betrachten Programme als Daten.)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 46
2.8 Verarbeitung von Zeichen
2.8.1 Darstellung von Zeichen:
• eine Möglichkeit: ASCII-Format (siehe nächste Folie)
• Darstellung eines Zeichens durch einen 8Bit Code
• Zugriffe auf einzelne Zeichen: Assemblerbefehle:
• Lade Byte (lb), speichere Byte (sb)
• Ladeoperation: lb $t0, 0($sp) (load byte)
Lädt ein Byte aus dem Speicher und platziert es in
die niederwertigen Bits eines Registers
• Speicheroperation: sb $t0, 0($a1) (save byte)
niederwertiges Byte in Speicherposition speichern
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 47
Darstellung von Zeichen: ASCII-Tabelle
Mit acht Bit (ein Byte) lassen sich in ASCII (American Standard Code for
Information Interchange) 28=256 Zeichen darstellen gemäß Konvention:
•
•
Groß- und Kleinbuchstaben unterscheiden sich um 32= 25
Nicht angegeben: u.a. Formatierungszeichen wie „Tab“ (9), „Carriage Return“ (13), „Backspace“ (8), „Null“
(0) (in C zur Markierung des Endes einer Zeichenkette verwendet).
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 48
2.8.2 Zeichenketten
Kombination von Zeichen zu Zeichenketten (strings)
•Darstellung von Zeichenketten: 3 typische Varianten
• Die erste Position der Zeichenkette wird reserviert
für die Länge der Zeichenkette.
• Eine zweite, zusätzliche Variable enthält die
Länge der Zeichenkette.
• Die letzte Position einer Zeichenkette wird durch
ein Sonderzeichen markiert. (z.B. in C verwendet)
• Beispiel: Zeichenkette „GdI3“ in C dargestellt durch
5 Byte mit den ASCII-Werten: 71, 100, 73, 51, 0.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 49
2.8.2 Zeichenketten
• Typische Operation auf Strings: Kopieren
• Beispiel: Kopieren eines Zeichenstrings unter
Prozedur strcpy kopiert Zeichenkette y auf x
void strcpy (char x[], char y[])
{
int i;
i = 0;
while ((x[i]=y[i]) != 0) /* Kopieren, Prüfen des i-ten Byte*/
i = i + 1;
}
Festlegung:
• Basisadresse des Feldes (array) x steht in $a0 und
Adresse von y in $a1
• $s0 wird für i verwendet.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 50
2.9 „Höhere Kontrollstrukturen“: Prozeduren
2.9.1 Allgemeines
• Prozeduren (Unterprogramme, Methoden) wichtigstes
Strukturierungskonzept moderner Programmiersprachen
• Moderne Rechner-Architekturen bieten Hardware-Unterstützung zur
effizienten Bearbeitung von Prozeduren
Konzept: Prozedurrahmen (procedure frame):
• Speicherblock, in dem alles abgelegt wird, was zur Verwaltung des
Prozeduraufrufs notwendig ist.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 52
2.9.1 Allgemeines
Vorteile des Konzeptes:
 Einheitliche Behandlung von Prozeduraufrufen, d.h.
 Abstraktion von unterschiedlichen Aufrufkonzepten:
• iterative und rekursive Prozeduren
• geschachtelte Prozeduren
• Im Prinzip wird auch ein entfernter Prozeduraufrufe (RPC, RMI) analog
bearbeitet
 Bem.: Prinzip wird auch an anderer Stelle eingesetzt:
u.a. beim Prozess- und Kontextwechsel durch das BS
Retten von Zuständen, Kontrollwechsel etc.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 53
2.9.1 Allgemeines
Schritte zur Ausführung einer Prozedur
• Parameter so bereit stellen, dass Prozedur darauf
zugreifen kann:
• Argumentregister $a0, $a1, $a2, $a3
• Eingangsparameter bleiben durch Prozedur
unverändert
• Ablaufsteuerung (control) der Prozedur übergeben:
• jal Prozeduradresse (jump and link)
• Sonderbefehl für Prozedurausführung: springt
zur angegebenen Adresse und speichert die
Adresse der folgenden Instruktion in $ra
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 54
2.9.1 Allgemeines
Schritte zur Ausführung einer Prozedur (Forts.)
•Benötigten Speicherbereich für Prozedur bereit stellen
• Prozedur ausführen
• Ergebniswert so bereit stellen, dass aufrufendes
Programm darauf zugreifen kann:
• Ergebniswertregister $v0,$v1
• Ablaufsteuerung an Aufrufstelle zurückgeben
durch Sprung zurück zum Ausgangspunkt:
• jr $ra (jr: jump register, ra: return address)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 55
2.9.1 Allgemeines
Nutzung des speicherprogrammierbaren Rechners:
• zur Realisierung einer Prozedur wird ein Register mit Adresse der aktuell
ausgeführten Instruktion benötigt
• Dieses Register nennt man traditionell program counter (PC), gemeint ist
das „instruction address register“
Problem: nach der Prozedurausführung muss bei der
korrekten Instruktion beim Aufrufer weitergearbeitet
werden: d.h. alter PC-Stand muss bewahrt werden
Lösung: Befehl jal speichert PC+4 in Register $ra.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 56
2.9.2 Übersetzung von Prozeduren in
Assembler
Einfache Parameterübergabe über Register:
• Die Register $a0-$a3 dienen zur Übergabe der ersten vier Parameter
• $v0-$v1 dienen zur Speicherung der Return-Werte
• $ra enthält die Rücksprungadresse zum Aufrufer
Probleme:
• Was ist bei mehr als 4 Parametern?
• Zur Bearbeitung der Prozedur werden auch Register benötigt, die
enthalten ggf, noch Werte des Aufrufers: was soll damit geschehen?
Retten? Überschreiben?
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 57
2.9.2 Übersetzung von Prozeduren in
Assembler
Antworten:
• gespeicherte Registerwerte des Aufrufers (Zustand) werden in Form
einer Keller-Datenstruktur (stack) im Speicher verwaltet (LIFO-Prinzip)
• Bem.: Stack-Verwaltung muss explizit in Assembler programmiert
werden
Ein Keller enthält:
• Argumentwerte, bei mehr als 4 Parametern
• die vor dem Prozeduraufruf gültigen Inhalte derjenigen Register, die von
der Prozedur verwendet werden.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 58
2.9.2 Übersetzung von Prozeduren in Assembler
Kellerverwaltung:
 Ein Register weist auf das letzte Element im
Kellerspeicher ($sp: stack pointer)
 Der Keller ist am „oberen Ende“ des Speichers
angeordnet und wächst in Richtung kleinerer
Speicheradressen (von oben nach unten)
 Push:
erniedrigt den Stack-Pointer
 Pop:
erhöht ihn
Synonyme Begriffe: Keller, Stapel, stack
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 59
$sp
2.9.2 Übersetzung von Prozeduren in Assembler
Notwendig für Verwaltung:
• Kellerpegel (engl. stack pointer) $sp muss vom
Assemblerprogrammierer manuell verwaltet werden
• Anpassung des Kellerpegels in 1-Wort-Schritten für
Speicherung oder Zurückspeicherung eines Registerwerts
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 60
Einfaches Beispiel für Prozedur
C-Programmtext
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
}
MIPS-Assembler
first_proc:
Phase 1: Registerinhalte auf den
Stack retten
Phase 2: Berechnungen
durchführen
Phase 3: Resultatwert speichern
Phase 4: Register zurückspeichern
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 61
Keller (stack)
hohe Adresse
$sp (vor Phase 1)
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
Phase 1: Registerinhalte auf den
return f;
}
Stack retten
[sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Phase 2: Berechnungen
durchführen
Phase 3: Resultatwert speichern
Phase 4: Register zurückspeichern
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 62
sub ist ein Pseudobefehl, der mit
Registern bzw. kleinen
Konstanten arbeiten kann (siehe
MIPS-R2000 Befehlssatz).
Keller (stack)
hohe Adresse
$sp (vor Phase 1)
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
Phase 1: Registerinhalte auf den
return f;
}
Stack retten
[sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Phase 2: Berechnungen
durchführen
Phase 3: Resultatwert speichern
Phase 4: Register zurückspeichern
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 63
Keller (stack)
hohe Adresse
$sp (vor Phase 1)
$t1
$t0
$sp (nach Phase 1)
$s0
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
Phase 1: Registerinhalte auf den
return f;
}
Stack retten
[sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Phase 2: Berechnungen
durchführen
Phase 3: Resultatwert speichern
Phase 4: Register zurückspeichern
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 64
Keller (stack)
hohe Adresse
$sp (vor Phase 1)
$t1
$t0
$sp (nach Phase 1)
$s0
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
}
Phase 2: Berechnungen
durchführen
Phase 1: [sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Keller (stack)
hohe Adresse
Phase 3: Resultatwert speichern
Phase 4: Register zurückspeichern
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 65
$t1
$t0
$sp (nach Phase 1)
$s0
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
}
Phase 2: Berechnungen
durchführen
Phase 1: [sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Keller (stack)
add $t0, $a0, $a1
hohe Adresse
add $t1, $a2, $a3
sub $s0, $t0, $t1
$t1
Phase 3: Resultatwert speichern
$t0
Phase 4: Register zurückspeichern
$s0
$sp (nach Phase 1)
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 66
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
Phase 3: Resultatwert speichern
}
Phase 1: [sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Phase 2: add $t0, $a0, $a1
add $t1, $a2, $a3
sub $s0, $t0, $t1
Keller (stack)
hohe Adresse
$t1
Phase 4: Register zurückspeichern
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 67
$t0
$sp (nach Phase 1)
$s0
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
Phase 3: Resultatwert speichern
}
Phase 1: [sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Phase 2: add $t0, $a0, $a1
add $t1, $a2, $a3
sub $s0, $t0, $t1
[move $v0, $s0]
Phase 4: Register zurückspeichern
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 68
Keller (stack)
hohe Adresse
$t1
$t0
$sp (nach Phase 1)
$s0
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
}
Phase 4: Register zurückspeichern
Phase 1: [sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Phase 2: add $t0, $a0, $a1
add $t1, $a2, $a3
sub $s0, $t0, $t1
Phase 3: [move $v0, $s0]
Keller (stack)
hohe Adresse
$t1
$t0
$sp (nach Phase 1)
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 69
$s0
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
}
Phase 4: Register zurückspeichern
Phase 1: [sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Phase 2: add $t0, $a0, $a1
add $t1, $a2, $a3
sub $s0, $t0, $t1
Phase 3: [move $v0, $s0]
lw $s0, 0($sp)
lw $t0, 4($sp)
lw $t1, 8($sp)
[add $sp, $sp, 12]
Phase 5: Rücksprung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 70
Keller (stack)
hohe Adresse
$sp (nach Phase 4)
$t1
$t0
$sp (nach Phase 1)
$s0
niedrige Adresse
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
}
Phase 5: Rücksprung
Phase 1: [sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Phase 2: add $t0, $a0, $a1
add $t1, $a2, $a3
sub $s0, $t0, $t1
Phase 3: [move $v0, $s0]
Phase 4: lw $s0, 0($sp)
lw $t0, 4($sp)
lw $t1, 8($sp)
[add $sp, $sp, 12]
Keller (stack)
hohe Adresse
$sp (nach Phase 4)
niedrige Adresse
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 71
Einfaches Beispiel für Prozedur
int first_proc (int g, int h, int i, int j)
{
int f;
f = (g + h) – (i + j);
return f;
}
Phase 5: Rücksprung
Phase 1: [sub $sp, $sp, 12]
sw $t1, 8($sp)
sw $t0, 4($sp)
sw $s0, 0($sp)
Phase 2: add $t0, $a0, $a1
add $t1, $a2, $a3
sub $s0, $t0, $t1
Phase 3: [move $v0, $s0]
Phase 4: lw $s0, 0($sp)
lw $t0, 4($sp)
lw $t1, 8($sp)
[add $sp, $sp, 12]
jr $ra
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 72
Keller (stack)
hohe Adresse
$sp (nach Phase 4)
niedrige Adresse
Einfaches Beispiel für Prozedur
Anmerkungen zum Beispiel:
• Annahme war: die Werte der verwendeten Register
$t0, $t1, $s0 werden gesichert und müssen nach Beendigung
der Prozedur zurück gespeichert werden.
• Zur Vermeidung von Speicheroperationen für Register, deren
Werte nicht verwendet: zwei Klassen von Registern:
• $t0 - $t9: 10 Register für temporäre Variablen, deren
Inhalte von der aufgerufenen Prozedur verändert werden
können und nicht gesichert werden müssen.
• $s0 - $s7: 8 Register für langlebige Variablen, die von aufgerufenen Prozeduren nicht verändert werden dürfen.
D.h. Inhalte müssen nach Aufruf und Abarbeitung einer Prozedur
gesichert bzw. wiederhergestellt sein.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 73
2.9.3 Geschachtelte Prozeduren (nested)
Beispiel zur Motivation der Problematik
• Hauptprogramm (main) ruft Prozedur A auf:
Effekt: main belegt Argumentregister $a0 und
Rücksprungregister $ra
• Prozedur A ruft Prozedur B auf:
Effekt: A belegt Argumentregister $a0 und
Rücksprungadresse $ra.
Probleme: Konflikte in $a0 und Register $ra !
• Rücksprungadresse in das Hauptprogramm
main geht verloren!
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 74
2.9.3 Geschachtelte Prozeduren (nested)
Schwierigkeiten:
• Alle Prozeduren verwenden dieselben Register für
ihre Argumente ($a0 - $a3).
• Alle Prozeduren verwenden ein einziges (dasselbe)
Rücksprungregister ($ra).
• Alle Prozeduren verwenden die Register ($s0 - $s7).
Eine mögliche Lösung:
• Die aufrufende Prozedur (caller) sichert die jeweils
benötigten der Argumentregister ($a0 - $a3) und
temporären Register ($t0 - $t9) auf den Stack
(„push“-Operation).
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 75
2.9.3 Geschachtelte Prozeduren (nested)
Eine mögliche Lösung: (Forts.)
• Die aufgerufene Prozedur (callee) sichert auf
dem Stack die Rücksprungregister ($ra) und die von
ihr zu verwendenden langlebigen Register ($s0 - $s7)
• Der Kellerpegel (stack pointer) $sp wird angepasst
gemäß der Anzahl der gespeicherten Register
• Beim Rücksprung aus der aufgerufenen Prozedur
werden alle gesicherten Register zurück geladen
(„pop“-Operation) und der Kellerpegel zurück gesetzt.
Bem.: Rekursive Prozeduraufrufe sind ein Spezialfall
von geschachtelten Aufrufen, analoge Behandlung
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 76
2.9.3 Geschachtelte Prozeduren (nested)
Beispiel: Rekursiver Prozeduraufruf
C-Programmtext: Berechnung der Fakultät n!
int fact (int n)
{
if (n < 1) return (1);
else return (n * fact(n-1));
}
Zwischenüberlegung: Umformung in C
int fact (int n)
{
int t0;
if (n < 1) t0 = 1;
else t0 = 0;
if (t0 == 0) goto L1;
return (1);
L1:
return (n * fact(n-1));
}
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 77
Beispiel (Forts.):
MIPS-Assembler (mit Verwendung direkter
Addition/Subtration von Konstanten)
fact:
L1:
[sub
sw
sw
[slt
beq
[add
$sp,$sp,8]
$ra, 4($sp)
$a0, 0($sp)
$t0,$a0,1]
$t0,$zero,L1
$v0,$zero,1]
[add
jr
[sub
jal
lw
lw
[add
mul
jr
$sp,$sp,8]
$ra
$a0,$a0,1]
fact
$a0, 0($sp)
$ra, 4($sp)
$sp,$sp,8]
$v0,$a0,$v0
$ra
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 78
# Anpassung des Kellerpegels um 2 Worte
# Speicherung der Rücksprungadresse
# Speicherung des Arguments n
# Test auf n < 1
# falls n >=1, gehe zu L1
# Ergebnis ist 1
# Zurückspeichern von $a0, $ra unnötig bei n<1
# Entfernen („pop“) zweier Worte vom Stapel
# Rücksprung hinter jal
# falls n>=1: ersetze Argument n durch n-1
# Aufruf von fact mit (n-1)
# Rückkehr von jal; Rückspeicherung Argument n
# Rückspeicherung der Rücksprungadresse
# Entfernen zweier Worte vom Kellerpegel
# Ergebnis ist n * fact(n-1); Multiplikation s.Kap.4
# Rücksprung zum aufrufenden Programm
Langlebige und temporäre Registerwerte
Inhalte der Register nach Aufruf einer Prozedur:
langlebig
temporär
(bzw. zu erhalten)
(bzw. nicht zu erhalten)
langlebige Register: $s0 - $s7
temporäre Register: $t0 - $t9
Kellerpegelregister: $sp
Argumentregister: $a0 - $a3
Rücksprungadressregister: $ra
Ergebniswertregister: $v0
Keller (stack) oberhalb des Kellerpegels
(stack pointer)
Keller (stack) unterhalb des Kellerpegels
(stack pointer)
Die Inhalte von Rahmenzeigerregister (frame pointer register) $fp und
Globalem-Zeiger-Register (global pointer register) $gp sind
gegebenenfalls auch zu erhalten.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 79
2.9.4 Speicherverwaltung: Prozedurrahmen
• Speicherung aller lokalen Variablen und Datenstrukturen einer Prozedur,
die nicht in die verfügbaren Register passen, auf dem Stack
• Das Kellersegment (stack segment) mit den Daten eines Prozeduraufrufs
heißt Prozedurrahmen (procedure frame, activation record).
• Rahmenzeiger (frame pointer) $fp zeigt auf Anfang des
Prozedurrahmens.
• Über $fp sind lokale Prozedurdaten unabhängig vom aktuellen
Kellerpegel ($sp) adressierbar
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 80
Verwaltung der Prozedurrahmen
vor
Prozeduraufruf
•
•
während
Prozedurausführung
nach
Prozeduraufruf
Rahmenzeiger $fp zeigt auf erstes Wort des Rahmens; er verändert sich
während Prozedurausführung nicht.
Kellerpegel $sp zeigt auf Anfang des Stacks; er kann sich während
Prozedurausführung verändern.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 81
Aufgabenverteilung
Frage: Welche Informationen schreibt Aufrufender (caller) welche
Aufgerufener (callee) in den Rahmen ?
Antwort: allgemeine Konvention
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 82
Prolog des Aufrufers
Prolog des Aufrufers (caller)
(vor Prozeduraufruf)
• Sichern aller Register, die der Aufrufer auch nach dem Aufruf benötigt.
• MARS: Register: $a0 - $a3, $t0 - $t9, $v0,$v1
• Übergabe der Eingabeparameter beim MARS:
• Die ersten 4 Argumente in den Registern $a0, ..., $a3
• Die restlichen in umgekehrter Reihenfolge auf den Keller
• Bei „Call-by-Value“-Parametern: Laden des Wertes
• Bei „Call-by-Reference“-Parametern:
• Laden der Adresse (mit la-Befehl)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 83
Beispiel für Prolog-Schema für Caller
main: <...>
[sub
sw
sw
# Berechnungen im Hauptprogramm
# --- Prolog des Aufrufers: --$sp,$sp,8] # Platz auf Stack reservieren (2 Worte f. 2 Regist.)
$t0, 4($sp) # Speicherung des noch benötigten Inhalts von
$t1, 0($sp) # $t-Registern (hier: $t0, $t1) vom Aufrufer selbst
[move $a0, $t5]
# Argumente übergeben (hier nur eines)
Aufruf der Prozedur mit jal-Befehl,
• d.h. Start der Prozedur durch Sprung zu deren
erstem Befehl.
• Wichtig: jal sichert automatisch die Rücksprungadresse des Aufrufers im Register $ra.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 84
Epilog des Aufrufers
Epilog des Aufrufers (caller)
(nach Rückkehr vom Prozeduraufruf)
• Wiederherstellen der gesicherten Register
• Wiederherstellen des ursprünglichen Kellerpegels
(stack pointer) (durch „Pop“ der Einträge):
$sp := $sp + (|Argumente| + |gesicherte Register|) × 4
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 85
Beispiel für Prolog/Epilog-Schema
main:
<...>
[sub
sw
sw
$sp,$sp,8]
$t0, 4($sp)
$t1, 0($sp)
# irgendwelche Berechnungen im Hauptprogramm
# --- Prolog des Aufrufers: --# Platz auf Stack reservieren (2 Worte f. 2 Regist.)
# Speicherung des noch benötigten Inhalts von
# $t-Registern (hier: $t0, $t1) vom Aufrufer selbst
[move
$a0, $t5]
# Argumente übergeben (hier nur 1)
jal
proc
# --- Aufruf der Prozedur ---
$t1, 0($sp)
$t0, 4($sp)
$sp,$sp,8]
# --- Epilog des Aufrufers: --# Registerinhalte wiederherstellen
#
# Kellerpegel zurücksetzen
lw
lw
[add
# Aufruf der Prozedur ist beendet
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 86
Prolog des Aufgerufenen

Prolog des Aufgerufenen (callee)
(vor Ausführung der Prozeduranweisungen)
• Speicherplatz reservieren: Versetzen des Kellerpegels:
$sp := $sp – (|zu sichernde Register| + |lokale Variablen|) × 4
• Sichern aller Register, die von der Prozedur verändert
werden; MARS:
• zuerst $fp sichern,
• restliche Register in beliebiger Reihenfolge,
• $ra sichern, falls weiterer Prozeduraufruf erfolgt!
• Rahmenzeiger $fp setzen: Element nach Eingabepar.
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 87
Beispiel für Prolog-Schema (Callee)
proc:
[sub
sw
sw
sw
sw
sw
[add
<...>
# Einsprungadresse der Prozedur
# --- Prolog des Aufgerufenen: --$sp,$sp,20] # Platz auf Stack reservieren (hier: 5 Worte)
# hier: 5 Register sichern
$fp, 16($sp)# “alten“ Rahmenzeiger sichern
$ra, 12($sp)# Rücksprungadresse sichern
$s0, 8($sp)# die benötigten $s-Register müssen von der
$s1, 4($sp)# aufgerufenen Prozedur gesichert werden
$s2, 0($sp)#
$fp, $sp,20]# Rahmenzeiger erstellen
# Prozedurkörper mit eigentlichen Befehlen
# --- Epilog des Aufgerufenen: ---
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 88
Epilog des Aufgerufenen

Epilog des Aufgerufenen (callee)
(nach Ausführung des Prozedurkörpers)
• Rückgabe des Funktionswertes
• MARS: in den Registern $v0 bzw. $v1
• Wiederherstellen der gesicherten Registerinhalte
• z.B. Rahmenzeiger $fp, Rücksprungadresse $ra
• „Pop“ der für die Prozedur angelegten Werte durch
Zurücksetzen des Kellerpegels (stack pointer) $sp
• $sp := $sp + (|gesicherte Register| + |lokale Variablen|) × 4
• Rücksprung zum Aufrufer: im MARS durch: jr $ra
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 89
Beispiel für Prolog/Epilog-Schema (Forts.)
proc:
[sub
$sp,$sp, 20]
sw
sw
sw
sw
sw
[add
<...>
$fp, 16($sp)
$ra, 12($sp)
$s0, 8($sp)
$s1, 4($sp)
$s2, 0($sp)
$fp, $sp,20]
lw
$s2, 0($sp)
lw
$s1, 4($sp)
lw
$s0, 8($sp)
lw
$ra, 12($sp)
lw
$fp, 16($sp)
[add
$sp, $sp,20]
Fachbereich Informatik
Frederik Armknecht | 90
jr | Prof. Dr.$ra
# Einsprungadresse der Prozedur
# --- Prolog des Aufgerufenen: --# Platz auf Stack reservieren (hier: 5 Worte)
# hier: 5 Register sichern
# “alten“ Rahmenzeiger sichern
# Rücksprungadresse sichern
# die benötigten $s-Register müssen von der
# aufgerufenen Prozedur gesichert werden
#
# Rahmenzeiger erstellen
# Prozedurkörper mit eigentlichen Befehlen
# --- Epilog des Aufgerufenen: --# $s-Registerinhalte wiederherstellen
#
#
# Rücksprungadresse wiederherstellen
# Rahmenzeiger wiederherstellen
# Kellerpegel zurücksetzen (pop)
# Rücksprung zum Aufrufenden
Pseudobefehle
 In den bisherigen Beispielen wurden unter anderem Pseuobefehle
verwendet.
 Diese waren durch Klammern („[…]“) markiert.
 Pseudobefehle sind Befehle, die es nicht im Maschinenbefehlssatz gibt.
 Einige Assembler unterstützen bestimmte Pseudobefehle, um die
Programmierung zu erleichtern.
 Beispiel: move $t0, $t1 (Kopiere Inhalt eines Registers ($t1) in ein
anderes ($t0))
 Einen solchen Befehl gibt es nicht!
 Mögliche Realisierung: add $t0, $t1, $zero (Addiere Null auf $t1 und
schreibe das Ergebnis in $t0)
 Weiteres Beispiel: Arithmetik mit Konstanten (siehe folgende Folien)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 91
2.10 Adressierung
MIPS-Befehlsformat „R“:
• Operanden sind immer Register
• Beispiele: add und sub
Schwächen der bisherigen Instruktionen:
• Die Verwendung von Konstanten ist unhandlich:
• über ein spezielles Register ($zero) oder
• Ablage der Konstante im Speicher an bekannter
Stelle, bzw. erst Laden in ein Register
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 92
2.10 Adressierung
• Konstanten (z.B. für Inkrement/Dekrement-Operationen bei Datenzugriffen in Schleifen) treten häufig auf,
z.B. C Compiler gcc: > 52% aller arithmetischen
Befehle nutzen Konstanten
 Effizienter Zugriff speziell auf kleine Konstanten ist
wünschenswert !
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 93
2.10.1 Konstanten als unmittelbare Operanden
Lösung: I- Befehlsformat (immediate):
• Konstanten als unmittelbare Operanden
op
rs
rt
6 Bit
5 Bit
5 Bit
Beispiel:
immediate
16 Bit
addi $sp, $sp, 4
Dezimaldarstellung
8
29
29
Binärdarstellung
001000
11101
11101
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 94
# $sp = $sp + 4
4
0000 0000 0000 0100
Weiteres Beispiel

MIPS:

unmittelbare Adressierung in MIPS:
slti $t0, $s1, 10

slt
# falls $s1 < $s2: $t0=1, sonst $t0=0
$t0, $s1, $s2
Dezimaldarstellung
10
17
8
Binärdarstellung
001010
10001
01000
# falls $s1 < 10: $t0=1, sonst $t0=0
10
0000 0000 0000 1010
Vorteil der direkten Adressierung: Die Verwendung häufig
vorkommender, kleiner Konstanten wird effizient (schnell) ausgeführt !
Frage: Was tun, wenn Konstante größer als 216-1 = 65535 ist,
und mehr als 16 Bit zur Darstellung benötigt ?
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 95
Behandlung großer Konstanten

maximal 32 Bits große Konstanten (d.h. 232-1 = 4,29... ×109)

Der Befehl lui (load upper half word immediate) lädt angegebene
Konstante in die höherwertigen 16 Bits des Zielregisters.
Beispiel:
lui $t0, 255

Binärdarstellung
Inhalt von $t0

00000
01000
0000 0000 1111 1111
0000 0000 1111 1111
0000 0000 0000 0000
Setzen der niederwertigen 16 Bits von $t0 z.B. mit
addi $t0, $t0, 2304
Inhalt von $t0

001111
0000 0000 1111 1111
0000 1001 0000 0000
Laden einer Zahl mit lui in höherwertige 16 Bits entspricht
Multiplikation mit 216 !
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 96
2.10.2 Adressierung von Sprungzielen

Einfachste Sprungzieladressierung in MIPS im J-Format:
j 10000
# go to Position 10000
Dezimaldarstellung

2
10000 (eigentlich: 2500)
6 Bit
26 Bit (für Sprungadresse)
Bedingte Verzweigung mit bne oder beq benötigt neben der Sprungadresse
zwei Operanden:
Beispiel:
bne $s0,$s1,Exit
# go to Exit, if $s0 != $s1
Dezimaldarstellung
5
16
17
6 Bit
5 Bit
5 Bit
Exit
16 Bit (für Sprungadresse)

Problem: Wie kann man größere Adressen als 216-1 realisieren?

Beobachtung: Verzweigungen in Schleifen und Fallunterscheidungen haben
Sprungadressen „in der Nähe“ der aktuellen Instruktion

Idee: Verwende relative Adressierung zum Instruktionsadress-Register PC
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 97
while (save[i] == k)
i = i + j;
Beispiel: Erneut: While-Schleife
MIPS:
80000 Loop:
add $t1,
add $t1,
add $t1,
lw $t0,
bne $t0,
add $s3,
j Loop
$s3, $s3
$t1, $t1
$t1, $s6
0($t1)
$s5, Exit
$s3, $s4
# $t1=2×i
# $t1=4×i
# $t1=Adresse[save(i)]
# $t0=save[i]
# falls save[i] != k, go to Exit
#i=i+j
Achtung: PC wird
# go to Loop
jeweils vor eigentlicher
Befehlsausführung um
4 erhöht.
Exit:
Darstellung in Maschinencode (symbolisch):
80000
0
19
19
9
0
32
80004
0
9
9
9
0
32
80008
0
9
22
9
0
32
80012
35
9
8
0
80016
5
8
21
8
80020
0
19
20
80024
2
80028
...
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 98
19
80000
0
32
PC=
PC+8 (Byte)
(oder
PC+2 (words))
Verzweigungen mit Zielen, die weiter entfernt
sind
• Verzweigungsbefehle können Verzweigungen um
± 216-1 Speicherworte realisieren.
• Für weit entfernte Verzweigungen wird vom Assembler eine
indirekte Verzweigungsmethode implementiert:
• invertierter Verzweigungsbefehl
• unbedingter Sprung zum Sprungziel (26 statt 16 Bit
Adresse)
Beispiel: beq $s0, $s1, L1 wird ersetzt durch
bne $s0, $s1, L2 #
j L1 # unbedingter Sprung, ‚weite Entfernung‘
L2:
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 99
Zusammenfassung der Adressierungsmodi
1. Unmittelbare Adressierung: Operand ist Konstante im Befehl selbst.
2. Registeradressierung: Operand ist Register
3. Basisadressierung: Operandenadresse ist Summe von Registerinhalt und
Konstante im Befehl
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 100
Zusammenfassung der Adressierungsmodi
4. PC-relative Adressierung: Operandenadresse ist Summe von PC und
Konstante im Befehl
5. Pseudodirekte Adressierung: Sprungadresse setzt sich aus 26 Bits im
Befehl und (!) den oberen 4 Bits im PC zusammen
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 101
Zusammenfassung: MIPS-Operanden
• einfache Befehle mit je 32 Bits
• sehr strukturiert, kein überflüssiges „Gepäck“
• nur drei Befehlsformate
Aufgabe des Compilers ist es, Leistung zu erbringen:
• Als Programmierer dem Compiler wo immer möglich helfen!
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 102
Bisherige MIPS-Instruktionen
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 103
Design Alternative: CISC
• Bereitstellung leistungsfähigerer Operationen
mit Ziel der Reduktion der auszuführenden Befehle
• Gefahr ist eine langsamere Taktzeit und/oder
eine höhere, durchschnittliche Anzahl von Takten
per Instruktion
• RISC (reduced instruction set computer) versus
• CISC (complex instruction set computer):
• fast alle neuen Instruktionssätze seit 1982 waren RISC
z.B. MIPS, Sun SPARC, Hewlett-Packard PA-RISC,
IBM/Motorola PowerPC, DEC Alpha
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 104
2.11 Fazit: Vom C-Programm zur Ausführung
C-Programm
Compiler
Assemblerprogramm
Assembler
Objektcode:
Maschinensprachmodul
Binder
(Linker)
Executable:
Maschinenprogramm
Lader
(Loader)
Speicher
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 105
Objektcode:
Bibliotheksroutinen
2.11 Fazit: Assemblerprogrammierung
• über Adressierung: Zugriff auf beliebige Objekte im
Speicher: flexibel, hoch performant
• Aber: kein Schutz durch Typisierung, z.B. IntegerWert kann beliebig als Adresse interpretiert werden
• Assemblerprogramme sind maschinenabhängig,
d.h. nicht portierbar
• Assemblersprache:
• viel einfacher als mit Binärzahlen umzugehen
• niedriges Niveau der Konzepte, darum Programmentwicklung schwierig (bzw. herausfordernd!)
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 106
2.11 Fazit: Assemblerprogrammierung
• Programmtext in Assembler wird schnell sehr
lang und unübersichtlich und damit fehleranfällig
• nur wenige Konzepte für Kontrollstrukturen,
Programmsteuerungsfluss: schwer wartbarbar
• kein „Information Hiding“: z.B. bei geschachtelten
Prozeduren über Rahmenzeiger-Kette beliebiger
Zugriff auf Daten der vorherigen Prozeduraufrufe!
Einsatzbereiche für Assemblerprogrammierung:
• Bereiche die sehr effizienten Code benötigen, wie
• Eingebettete Systeme, Controller,
• elektronische Steuerungen: Auto, Flugzeug, …
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 107
2.11 Fazit:
Eingebettete Systeme: Die Spitze des Eisbergs
• In Vorlesung betrachtet: Hochleistungsprozessoren für
allgemeine Computeranwendungen.
• Aber: Die meisten Anwendungen der digitalen
Datenverarbeitung findet man in Geräte des
täglichen Lebens (embedded)
• Markt für eingebettete (Computer-)Systeme wächst sehr
stark
• Deutschland hat eine führende Position bei der Entwicklung
eingebetteter Systeme!
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 108
Eingebettete Prozessoren und Prozessorkerne
• ARM, 486SX, Hitachi SH7000, …
• nur ein Programm
• einfache, oft Realzeit-Betriebssysteme
• Mobiltelefone, Consumerelektronik
Microcontroller
• extrem Kosten sensitiv
• geringe Wortbreite – 8-bit üblich
• bei weitem die höchsten Stückzahlen
• Automobil, Fahrstühle, Rolläden, Klimaanlage, Toaster, ..
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 109
Zunehmende Stückzahl
General Purpose Prozessoren – Hohe Leistung
• Pentiums, Alphas, SPARC, …
• nützlich für allgemeine Software
• komplexe Betriebssysteme – Unix, Win XP
• Workstations, PCs
Zunehmende Kosten
2.11 Fazit: Prozessorklassen
2.11 Fazit: Der Prozessor-Design-Raum
Leistung
Anwendungsspezifische Architekturen
für hohe Leistung
Eingebettete
Prozessoren
Mikroprozessoren
Leistung ist alles
& Software regiert
Microcontroller
Kosten sind alles!
Kosten
Fachbereich Informatik | Prof. Dr. Frederik Armknecht | 110