fakultät für informatik - Informatik 10

FAKULTÄT FÜR INFORMATIK
TECHNISCHE UNIVERSITÄT MÜNCHEN
Lehrstuhl für Rechnertechnik und Rechnerorganisation
Prof. Dr. Arndt Bode
Einführung in die Rechnerarchitektur
Wintersemester 2016/2017
Zentralübung 1
28.10.2016
Maschinennahe Programmierung (1)
Ganzzahlige Arithmetik mit dem 80386
Grundlagen zum Programmiermodell des 80386
Um Daten (z.B. Zahlenwerte) zu verarbeiten, werden diese bei fast allen Prozessoren in sogenannten Registern gespeichert. Der Intel 80386 hat dazu vier Allzweck-Datenregister mit
den Namen EAX, EBX, ECX, EDX von je 32 Bit Breite, in denen Operanden und Ergebnisse arithmetischer und anderer Operationen gespeichert werden können. Damit können also je
nach Interpretation der Register Werte zwischen -231 und 231 − 1 oder zwischen 0 und 232 − 1
dargestellt werden.
Eine Besonderheit der Intel 80386 Prozessoren ist, daß sich jedes der vier Register aus der
Data-Gruppe (EAX, EBX, ECX und EDX) auch noch in 16Bit und als Registerpaar“ aus
”
zwei 8-Bit Registern ansprechen lässt (siehe Abb. 1).
Das 32-Bit Wort, das in einem Data-Register (z. B. EAX) gespeichert ist, ist mit seinen unteren 16Bit in AX zugreifbar. AX ist wiederum in das niederwertige Byte (low byte) und das
höherwertige Byte (high byte) geteilt. Über die zusätzlichen Registernamen AL (AX Low) und
AH (AX High) lassen sich dann das Low-Byte bzw. das High-Byte des EAX/AX Registers
ansprechen. Hieraus folgt natürlich, daß EAX, AX, AL und AH nicht unabhängig voneinander
benutzbare Register sind! Zum Beispiel sich der Wert von AX als 256 × AH + AL. Analoges
gilt für das EBX, das ECX und das EDX Register.
Weitere Register
Es gibt mit ESI, EDI und EBP noch drei weitere fast-Allzweck“ Register, diese sind aber
”
ausschließlich mit 16 oder 32Bit nutzbar; es gibt aus historischen Gründen keine 8Bit-Teile.
Einen Gesamtüberblick aller 80386-Register gibt es in der nächsten Übung.
1
31
15
8 7
0
EAX
AH
AL
AX
EAX
BH
BX
BL
EBX
CH
CX
CL
ECX
DH
DX
DL
EDX
SI
ESI
DI
EDI
BP
EBP
Abbildung 1: Registernamen der wichtigsten 80386-Register
Assembler
Die Befehle eines Prozessors sind zunächst verschiedene Zahlenkombinationen, sog. Opcodes“
”
(=Operation Codes, beim 80386 typ. 1-16 Bytes lang), die die auszuführende Aktion beschreiben und vom Prozessor direkt verarbeitet werden können.
Da diese Zahlen nicht besonders eingängig sind, gibt es für den Programmierer eine Vereinfachung, sogenannte Mnemonics“. Dies sind einfach zu merkende, textuelle Befehle,
”
die mit Übersetzungstabellen in die benötigten Zahlenwerte umgesetzt werden können. Die
Übersetzung kann auch mit einem speziellen Programm erfolgen, dieses wird dann Assembler“
”
genannt. Die Rückübersetzung in Mnemonics zur Fehlersuche etc. wird als Disassemblierung“
”
bezeichnet.
Hinweis: Bei den Befehlen ist die Groß/Kleinschreibung nicht wichtig. Die Befehle werden im
folgenden meist groß geschrieben, um sie stärker hervorzuheben.
Grundrechenarten mit dem 80386
Es stehen alle 4 Grundrechenarten und die Bildung des Zweierkomplements zur Verfügung:
2
Befehl
ADD Ziel, Quelle
SUB Ziel, Quelle
NEG Ziel
MUL Quelle
DIV Quelle
Erläuterung
Ziel := Ziel + Quelle
Ziel := Ziel − Quelle
Ziel := −Ziel (Bildung des Zweierkomplements)
EDX:EAX := EAX*Quelle (vorzeichenlose Multiplikation mit
64Bit-Ergebnis, die niederwertigen 32Bit sind in EAX)
EAX := (EDX:EAX)/Quelle, EDX:=Rest von EAX/Quelle
vorzeichenlose 64Bit-Division mit ganzahligem Ergebnis in
EAX und Rest in EDX
Als Ziel dürfen (zunächst) nur Register angegeben werden (Erweiterung in Übung 2). Quelle
kann ein Register oder auch ein direkter Zahlwert (Konstante, sogenannte Immediate“) sein.
”
Die Verarbeitungsbreite (32, 16, 8Bit) wird von den Operandregistern definiert.
MUL und DIV erlauben nur ein Register als Quelle, das Ziel ist immer EAX/AX bzw.
EDX/DX! Die Division erwartet bei einem 16Bit-Register als Divisor einen 32Bit-Wert als
Ausgangswert, für einen 32-Bit-Divisor einen 64Bit-Wert. Dieser setzt sich aus DX bzw. EDX
für die höherwertigen 16 bzw. 32Bit und AX/EAX für die niederwertigen 16/32 Bit zusammen
(Notation DX:AX bzw. EDX:EAX). Eine Division durch 0 führt erst bei der Ausführung zu
einem Fehler (sog. Ausnahme). Diese bricht das Programm normalerweise ab.
Für ADD Ziel,1 bzw. SUB Ziel,1 gibt es aus historischen Gründen noch die Befehle INC Ziel
bzw. DEC Ziel. Diese erhöhen (inkrementieren) bzw. erniedrigen (dekrementieren) das Ziel um
1. Da diese Befehle ausser dem Register keine Operanden brauchen, sind sie kürzer und waren
daher früher schneller in der Ausführung.
Beispiele:
ADD EAX,EBX
ADD AX,BX
SUB EBX,10
NEG ECX
MUL ECX
DIV EBX
INC BL
DEC ESI
aber:
ADD AX,BL
ADD AX,EBX
MUL 10
MOV SL,0
EAX := EAX+EBX (32Bit Addition)
AX := AX+BX (16Bit Addition)
EBX := EBX-10
ECX := -ECX
EDX:EAX := EAX*ECX
EAX := (EDX:EAX)/EBX, EDX := Rest (EAX/EBX)
BL := BL+1 (8Bit)
ESI := ESI-1
FALSCH!
FALSCH!
FALSCH!
FALSCH!
8 und 16 Bit können nicht direkt addiert werden!
16 und 32 Bit können nicht direkt addiert werden!
MUL kann nur Quellregister, keine Konstanten!
SI hat keinen ansprechbaren 8Bit-Teil!
Hinweis: Für vorzeichenbehaftete Multiplikation und Division gibt es spezielle Befehle, die etwas
flexibler in den Parametern sind. Diese werden später behandelt.
Transportbefehl MOV
Um Daten ohne Veränderung zwischen den Registern zu bewegen, existiert der MOV-Befehl
( Move“). Dieser setzt bzw. kopiert je nach angegebenem Register (8, 16 oder 32Bit) einen
”
Wert in dieses. Kopieren heißt in diesem Zusammenhang, dass das zu kopierende Register
(d.h. die Quelle) nicht verändert wird! Die Bezeichnung Move (verschieben) ist also nicht ganz
korrekt.
3
Befehl
Erläuterung
MOV Ziel, Quelle Ziel = Quelle
Ziel kann (vorerst) nur ein Register sein, die Quelle kann zunächst nur ein Register oder auch
eine Konstante sein. Mit einer Konstante kann z.B. der für MUL nötige Register-Multiplikator
geladen werden.
Beispiele:
MOV AX, 10H
MOV EAX, 10H
MOV EBX, EAX
MOV AL,BH
aber:
MOV BL,AX
MOV EAX,BL
MOV BL,300
Lade die 16Bit-Konstante 1016 nach AX
Lade die 32Bit-Konstante 1016 nach EAX
Kopiert den Inhalt von EAX nach EBX, EAX wird nicht verändert
Kopiert die oberen acht Bit von BX in die unteren 8 Bit von AX
(die oberen 24Bit von EAX werden nicht verändert)
FALSCH! 16Bit können nicht in 8Bit kopiert werden!
FALSCH! 8Bit können so nicht in 32Bit kopiert werden!
FALSCH! 300 passt nicht mehr in 8Bit!
Angabe symbolischer Konstanten
In manchen Fällen ist es aus Entwicklungsgründen ungünstig, direkt die Zahlkonstanten in die
Befehle zu schreiben. Um dies zu umgehen, ist es in allen Assemblern möglich, symbolische
Namen als Platzhalter anzugeben, die bei der Assemblierung durch einen anderswo definierten Wert ersetzt werden (Textersetzung). Diese Definitionen erfolgen üblicherweise mit einem
Pseudo-Befehl“ 1 , z.B. equ (equals). Die Symbole selbst (also Name mit Doppelpunkt) werden
”
auch als Marken bzw. Labels bezeichnet, sie können auch ohne Pseudobefehle benutzt werden,
um eine bestimmte Position zu markieren (dazu später mehr).
Beispiel:
startwert:
EQU 15
....
MOV EAX,startwert
; Lädt EAX mit ’startwert’, also 15
MOV EBX,startwert+1 ; Lädt EBX mit ’startwert+1’, also 16
1
Pseudo“ deshalb, weil es kein echter Prozessorbefehl ist, sondern eine Anweisung, die nur der Assembler
”
versteht.
4
Aufgaben
Aufgabe 1.1
Die ETI-Waschmaschine informiert den Benutzer nach dem Start über die geschätzte Gesamtdauer eines Waschprogramms. Diese berechnet sich aus 3 vom Waschprogramm abhängigen
Zeiten (Vorwäsche VW, Hauptwäsche HW, Schleudern SCH) und einem festen Wert, der das
abschliessende Sicherheitsabpumpen und Auflockern der Wäsche (Trommel kurz hin- und her
bewegen) beinhaltet.
☞ Schreiben Sie ein x86-Assembler-Programm, dass die Gesamtwaschzeit errechnet. Der feste
Wert betrage 50 Sekunden, die Sekundenzeiten für VW, HW und SCH sind bereits in den
16-Bit Registern AX, BX und CX abgelegt, das Rechenergebnis soll in DX stehen. Mehr als 4
Befehle sollten Sie nicht dazu benötigen.
Aufgabe 1.2
Unsere Waschmaschine zeigt dem Benutzer immer die aktuelle Temperatur des Waschwassers
an. Dazu werden die Daten eines Temperatursensors ausgewertet, der vorzeichenlose Werte
zwischen 0 und 255 liefert. Allerdings müssen diese Werte umgerechnet werden, da der Sensorwert 0 einer Temperatur von 100◦ C und Sensorwert 255 einer Temperatur von 10◦ C entspricht.
Ansonsten arbeitet der Sensor innerhalb dieses Bereichs linear.
☞ Wie muss man allgemein die aktuelle Temperatur aus dem gelieferten Sensorwert berechnen?
☞ Welche Probleme ergeben sich mit der Umrechnungsformel, wenn man nur mit ganzen
Zahlen rechnen kann? Wie kann man diese umgehen?
☞ Wie müsste ein Programmstück in x86-Assembler aussehen, das diese Temperaturberechnung möglichst fehlerfrei durchführt? Der Sensorwert liege vor Beginn der Rechnung im 8-Bit
Register BL, das Rechenergebnis soll im 32-Bit Register EAX stehen.
☞ Welche Möglichkeiten gibt es noch zur Umrechnung? Welche Vor- bzw. Nachteile haben sie?
Falls Sie noch Fragen haben, wenden Sie sich bitte an Ihre Tutoren oder
Marcel Meyer, E-Mail: [email protected]
5