Grundlagen der Informatik I Übung Studiengang Wirtschaftsingenieurwesen Wintersemester 2013/2014 Autor: Prof. Dr.-Ing. habil. Hans-Joachim Böhme HTW Dresden, Fachbereich Informatik/Mathematik Friedrich-List-Platz 1, 01069 Dresden E-Mail: [email protected] Hinweis: Die Rechte am Dokument liegen ausschließlich beim Verfasser. 1 Zahlendarstellung im Rechner Rechner „denken“ binär! Daraus lässt sich unmittelbar folgern: Alles, was sich mit binärer Codierung darstellen lässt, kann in einem Rechner verarbeitet werden. Allgemein handelt es sich bei allen behandelten Zahlensystemen inklusive des uns am geläufigsten Dezimalsystems um ein Stellenwertsystem oder Positionssystem. Stellenwertsystem: Stelle/Position bestimmt Wert der jeweiligen Ziffer niederwertigste Stelle steht rechts hat Basis b Zifferposition hat Wert, der Potenz der Basis b an der entsprechenden Stelle/Position entspricht o für n-te Position Wert bn-1 Zahlenwert z n b n ... z i b i ... z 0 b 0 Berechnung des Zahlenwertes (Interpretation der Zahl): 1) Multiplikation der Ziffern zi mit den zugehörigen Stellenwerten (Potenzen) bi 2) Summation/Addition der Produkte Für Zahlendarstellung im Rechner gilt: Basis b 2 Dies gilt für alle im Rechner verwendeten Zahlendarstellungen gleichermaßen, also auch für die vom Dual- bzw. Binärsystem abgeleiteten Oktal- und Hexadezimaldarstellungen. Oktalsystem Basis b 8 2 3 Hex System Basis b 16 2 4 Beispiele: Dualsystem: 2 5 0 2 4 1 2 3 1 2 2 1 21 1 20 101110 2 1 32 0 8 4 2 0 4610 1 82 0 81 7 80 6078 6 Oktalsystem: 6 64 0 8 7 1 384 0 7 39110 Hexadezimalsystem: 2 1 0 2 BE16 2 16 11 16 14 16 2 256 11 16 14 1 512 176 14 70210 Die Wertigkeit der Basis bestimmt den notwendigen Werteumfang der einzelnen Stellen (Ziffern, Koeffizienten) im Stellenwertsystem. Dual: Oktal: Hexadezimal: 0,1 0,1,...,7 0,1,...,15 2 Zustände kodierbar 8 Zustände kodierbar 16 Zustände kodierbar 2 Ziffernwerte 8 Ziffernwerte 16 Ziffernwerte Hexadezimal: [0,1,2,..., 9, A, B, C, D, E, F] Einstellige Hex-Zahl F drückt damit das Produkt 15 mal 160 aus Umwandlung vom Dezimalsystem in Dual-/Oktal-/Hexadezimalsystem Prinzip: fortgesetzte ganzzahlige Division der Dezimalzahl durch die entsprechende Basis liefert als Restwerte (modulo Operation) die Ziffern (Koeffizienten) für die jeweilige Potenz der Basis Beispiele: Dual: z10 = 46 46 : 2 = 23 23 : 2 = 11 11 : 2 = 5 5:2=2 2:2=1 1:2=0 Rest 0 Rest 1 Rest 1 Rest 1 Rest 0 Rest 1 niederwertigste Stelle höchstwertige Stelle z2 = 101110 2 Oktal: z10 = 391 391 : 8 = 48 48 : 8 = 6 6:8=0 Rest 7 Rest 0 Rest 6 niederwertigste Stelle höchstwertige Stelle z8 = 607 Hex: z10 = 702 702 : 16 = 43 43 : 16 = 2 2 : 16 = 0 Rest 14 = E niederwertigste Stelle Rest 11 = B Rest 2 höchstwertige Stelle z16 = 2BE Umwandlung vom Dualsystem in Oktal-/Hexadezimalsystem einfach, da alle Systeme die gleiche Basis 2 beinhalten Oktal: jeweils 3 Dualziffern bzw. –stellen zusammengefasst Hex: jeweils 4 Dualziffern bzw. –stellen zusammengefasst Beispiele: Dual > Oktal: z 2 101 110 z8 5 Dual > Hex: 6 z 2 1001 1101 z16 9 1310 9D16 3 2 Zahlendarstellung im Rechner (Fortsetzung) Mit der bislang behandelten Zahlendarstellung im Rechner können wir lediglich nichtnegative, ganze Zahlen repräsentieren, was natürlich nicht den tatsächlichen Gegebenheiten im Rechner entspricht. Wie werden nun vorzeichenbehaftete Zahlen und Brüche in einer „rechnerverständlichen“ Darstellungsform repräsentiert? Und wie rechnet der Rechner mit der ihm innewohnenden binären Zahlendarstellung? 2.1 Rechnen mit Dualzahlen 2.1.1 Wiederholung der schriftlichen Ausführung der Grundrechenarten im Dezimalsystem Schriftliche Addition: Von rechts beginnend mit Übertrag auf die jeweils nächsthöhere Stelle bzw. Potenz zur Basis 10 3 + 2 4 9 1 8 7 6 1 Summand Summand Übertrag 1 Ergebnis ---------------------------6 4 5 7 -------------Summe 6+1=7 Übertrag 0; 7+8=15 Übertrag 1; 9+Übertrag1+4=14 Übertrag 1; 2+Übertrag1+3=6 Schriftliche Subtraktion: Man "füllt" die abzuziehende Zahl (Zahl des Subtrahenden) soweit auf, dass die Zahl des Minuenden erreicht wird; auch hier gibt es Übertrag, nämlich immer dann, wenn die Zahl des Minuenden kleiner als die Zahl des Subtrahenden ist, was bedeutet, dass eine Zehnerpotenz übersprungen wurde Übertrag Ergebnis 2 1 7 9 5 6 1 4 Minuend Subtrahend -----------------------------7 8 7 1 1 1 ---------------Differenz 4 bis 11 = 7 Übertrag 1; 6+1 bis 15 = 8 Übertrag 1; 9+1 bis 17 = 7 Übertrag 1; 1+1 bis 2 = 0 Schriftliche Multiplikation: Ein Produkt ist die Addition gleicher Summanden, wobei ein Faktor den jeweiligen Summanden und ein weiterer Faktor die Anzahl der Summierungen darstellt. Dies ist insbesondere für die technische Realisierung im Rechner von Interesse, da man für das Ausführen einer Multiplikation eigentlich nur ein Addierwerk benötigt. Bei der schriftlichen Multiplikation wird die erste Zahl mit den einzelnen Ziffern der zweiten Zahl nacheinander, beginnend bei der letzten Stelle, multipliziert. Für jede 4 neue Ziffer wird eine neue Zeile benötigt. Man schreibt jede Multiplikation untereinander und addiert die einzelnen Werte. 37 x 31 = 1147 ---------37 111 ---------1147 Faktor1 x Faktor2 = Produkt Schriftliche Division: Wir beginnen von links aus zu suchen, welchen möglichst kurzen Abschnitt des Dividenden wir durch den Divisor teilen können. 871 : 5 = 174,2 5 ---------37 35 ---------21 20 ---------10 10 ---------0 Dividend : Divisor = Quotient Analog zu den Zahlen im Dezimalsystem lassen sich mit Dualzahlen die gängigen arithmetischen Grundoperationen Addition, Subtraktion, Multiplikation und Division durchführen. Tatsächlich werden die benötigten Algorithmen sogar einfacher und lassen sich effizient mit logischen Schaltungen elektronisch realisieren. Die Einführung von Dualzahlen in der Rechentechnik brachte daher viele Vorteile. 2.1.2 Grundrechenarten im Dualsystem Duale/binäre Addition: Die binäre Addition ist eine grundlegende Basisoperation in der Computerwelt. Will man zwei nicht negative Binärzahlen A und B addieren, kann man dies wie im Dezimalsystem tun. Nur muss man beachten, dass beim Ergebnis keine Zwei an der jeweiligen Stelle notiert wird, sondern eine Null und ein Übertrag an die nächste Stelle. Dies geschieht analog zu dem Fall einer Dezimaladdition, wenn sich eine Zahl größer oder gleich Zehn bei der Addition einer Stelle ergibt: Die Zahlen werden übereinander aufgeschrieben. Nun arbeitet man von rechts nach links alle Binärziffern (=Bits) von A und B simultan ab und erzeugt in jedem Zwischenschritt ein Ergebnisbit sowie ein Merkerbit (auch Übertrag genannt). Dabei werden die Bits entsprechend der Tabelle unten zusammengezählt. Alle 5 Ergebnisbits, von rechts nach links aneinandergereiht, stellen das Resultat dar. Entsteht beim letzten Zwischenschritt ein Merkerbit, so bekommt das Resultat links eine zusätzliche 1. Es gelten folgende Rechenregeln: 0+0=0 0+1=1 1+0=1 1 + 1 = 0 Übertrag 1 Am besten sieht man dies anhand eines Beispieles. Hier werden die Zahlen A und B zusammengezählt. In jedem Schritt wird ein anfallendes Merkerbit bei der nächsten Ziffer notiert. A = 10011010 (154 dezimal) B = 00110110 (54 dezimal) Merker = 11111 -------Ergebnis = 11010000 (208 dezimal) ======== Duale Subtraktion: Es gelten folgende Rechenregeln: 0−0=0 0 − 1 = −1 (dargestellt als 1 und Übertrag 1) 1−0=1 1−1=0 0 - 1 mit Übertrag 1 = 0 mit Übertrag 1 1 - 1 mit Übertrag 1 = 1 mit Übertrag 1 Es wird im nachfolgenden Beispiel die Subtraktion der dual codierten Dezimalzahlen 110 − 23 = 87 durchgeführt. Die kleinen Einsen in der dritten Reihe zeigen den Übertrag. Das Verfahren ist das Gleiche, wie es in der Schule für das Dezimalsystem unterrichtet wird. Etwas ungewohnt sieht der Fall 0-1 aus. Zum Beispiel im Fall 2 − 9 im Dezimalsystem, denkt man sich eine Zehnerstelle vor die Zwei, wodurch sich die Subtraktion 12 − 9 ergibt. Die gedachte Zehnerstelle wird dann als Übertrag an die nächste Stelle weitergereicht. Im Dualsystem geschieht das Gleiche. Aus 0 − 1 wird 10 − 1. Es kann als Ergebnis also eine 1 hingeschrieben werden, die vor die 0 gedachte Eins muss dann als Übertrag an die nächste Stelle geschrieben und von dieser zusätzlich abgezogen werden. Das Verfahren funktioniert (wie auch im Dezimalsystem) nicht, wenn der Minuend kleiner ist als der Subtrahend. Beispiel: A = 1101110 (110 dezimal) B = 10111 (23 dezimal) Merker = 1 111 -------Ergebnis = 1010111 (87 dezimal) Die Subtraktion einer positiven Zahl ergibt dasselbe Ergebnis wie die Addition zu einer negativen Zahl mit dem gleichen Betrag. 6 Duale Multiplikation: Es gelten folgende Rechenregeln: 0x0=0 1x0=0 0x1=0 1x1=1 Die Multiplikation wird im Dualsystem genauso durchgeführt wie im Dezimalsystem. Dadurch dass nur 0 und 1 als Ziffern vorkommen ist die schriftliche Multiplikation jedoch sogar einfacher. Das folgende Beispiel, in dem die Zahlen 1100 (12) und 1101 (13) multipliziert werden, zeigt die Vorgehensweise. Zuerst schreibt man die Aufgabenstellung in eine Zeile und zieht zur Vereinfachung einen Strich darunter. 1100 · 1101 ----------- 1100 · 1101 ----------1100 Die erste Ziffer des zweiten Faktors ist eine Eins und deshalb schreibt man den ersten Faktor rechtsbündig unter diese Eins. Auch für alle weiteren Einsen des zweiten Faktors schreibt man den ersten Faktor rechtsbündig darunter. 1100 · 1101 ----------1100 1100 0000 1100 Die so gewonnenen Zahlen zählt man dann zum Ergebnis der Multiplikation zusammen. 1100 · 1101 ----------1100 + 1100 + 0000 + 1100 ----------10011100 (156) 7 Ein besonders einfacher Fall ist die Multiplikation einer positiven Dualzahl mit der Zahl 10 (2). In diesem Fall muss lediglich an die positive Dualzahl eine 0 angehangen werden: 1101 · 10 = 11010 11010 · 10 = 110100 usw. Für diese Rechenoperation existieren einfache Befehle in der Digitaltechnik. Duale Division: Es gelten folgende Rechenregeln: 0 : 0 = nicht definiert 1 : 0 = nicht definiert 0:1=0 1:1=1 Im nachfolgenden Beispiel erfolgt die Division von 1000010 / 11 (entspricht 66:3 im Dezimalsystem): 1000010 ÷ 11 = 010110 Rest 0 (= 22 dezimal) − 011 ----00100 − 011 ---0011 − 011 ----000 − 00 --0 Bei der Division zweier positiver Dualzahlen verbleibt immer ein Rest 1, wenn die letzte Ziffer des Dividenden eine 1 ist. Die Anwendung der Modulo-Funktion mit dem Divisor 10 (2) auf positive Dualzahlen ergibt ergibt immer 1, wenn die letzte Ziffer des Dividenden 1 ist und 0, wenn die letzte Ziffer des Dividenden 0 ist: 1101 mod 10 = 1 1100 mod 10 = 0 Für diese Rechenoperation, die einer UND-Verknüpfung mit 1 entspricht, existieren einfache Befehle in der Digitaltechnik. 8 Ein besonders einfacher Fall ist die Division mit Rest einer positiven Dualzahl durch die Zahl 10 (2). In diesem Fall muss lediglich die letzte Ziffer des Dividenden gestrichen werden. Ist die letzte Ziffer des Dividenden eine 1, so verschwindet dieser Rest. Entspricht bei diesem Verfahren die Anzahl der Divisionen durch 2 der Anzahl der Stellen des Dividenden, so ist das Endergebnis immer 0: 1101 ÷ 10 = 110 110 ÷ 10 = 11 11 ÷ 10 = 1 1 ÷ 10 = 0 Für diese Rechenoperation existieren einfache Befehle in der Digitaltechnik. 9 3 Zahlendarstellung im Rechner (Fortsetzung) 3.1 Vorzeichendarstellung Darstellung ganzer Zahlen mit separatem Vorzeichen-Bit Als ganze Zahlen bezeichnet man die natürlichen Zahlen unter Hinzunahme der negativen Zahlen. Für die Kenntnis einer ganzen Zahl ist also nicht nur der absolute Zahlenwert nötig, sondern auch noch das Vorzeichen, '+' oder '-'. Für diese zwei Möglichkeiten benötigen wir also ein weiteres Bit an Information. So bietet sich zunächst eine Darstellung an, in der das erste Bit von links gesehen das Vorzeichen repräsentiert (0 für '+' und 1 für '-') und der Rest den Absolutwert. Diese Darstellung nennt man die Vorzeichendarstellung. Bei einer Breite von 4 Bit erhalten wir: 0000 = +0 0001 = +1 0010 = +2 0011 = +3 0100 = +4 0101 = +5 0110 = +6 0111 = +7 1000 = -0 1001 = -1 1010 = -2 1011 = -3 1100 = -4 1101 = -5 1110 = -6 1111 = -7 Bei näherem Hinsehen hat diese Darstellung aber eine Reihe von Nachteilen: Die Zahl 0 wird durch zwei verschiedene Bitfolgen darstellt (als '+0' und als '0'). Das Rechnen ist komplizierter geworden, man kann nicht mehr einfach zwei Zahlen untereinander schreiben und addieren. je breiter die Zahlendarstellung, umso größer ist die Zahl der ungenutzten Bits Im Folgenden wird eine Variante beschrieben, die diese Probleme vermeidet und deshalb zu einer gebräuchlichen Darstellung geworden ist, die Zweierkomplementdarstellung. Komplementdarstellung Die Zweierkomplementdarstellung ist die gebräuchliche interne Repräsentation ganzer positiver und negativer Zahlen. Sie kommt auf sehr einfache Weise zu Stande. Wir erläutern Sie zunächst für den Fall N = 4. Mit 4 Bits kann man einen Bereich von 24 = 16 ganzen Zahlen abdecken. Den Bereich kann man frei wählen, also z.B. die 16 Zahlen von -8 bis +7. 10 Man zählt nun von 0 beginnend aufwärts, bis man die obere Grenze +7 erreicht, anschließend fährt man an der unteren Grenze -8 fort und zählt aufwärts, bis man die Zahl -1 erreicht hat. Auf diese Weise erhält man nun folgende Zuordnung von Bitfolgen zu ganzen Zahlen: 1000 = -8 1001 = -7 1010 = -6 1011 = -5 1100 = -4 1101 = -3 1110 = -2 1111 = -1 0000 = 0 0001 = 1 0010 = 2 0011 = 3 0100 = 4 0101 = 5 0110 = 6 0111 = 7 Jetzt sieht man auch den Grund, wieso der Bereich von -8 bis +7 gewählt wurde und nicht etwa der Bereich von -7 bis +8: Bei dem mit 0 beginnenden Hochzählen wird bei der achten Bitfolge zum ersten Mal das erste Bit zu 1. Springt man also ab der 8. Bitfolge in den negativen Bereich, so hat man die folgende Eigenschaft: Bei den Zweierkomplementzahlen stellt das erste Bit das Vorzeichen dar. Das Zweierkomplement hat zudem den Vorteil, dass die '0' nur einmal vorkommt. Darstellbar sind mit dem Zweierkomplement die Zahlen von -2N-1 bis 2N-1-1. Zweierkomplementzahlen werden auch als signed binary numbers oder signed integers bezeichnet. Berechnung des Zweierkomplements Das Zweierkomplement erhält man, indem man zunächst das Einerkomplement bildet und anschließend 1 addiert. Das Einerkomplement erhält man durch bitweises Vertauschen der Werte 0 und 1. Man erhält zum Beispiel die Zweierkomplementdarstellung von -6, indem man zuerst die Binärdarstellung von +6, also (0110)2 bildet. Davon bildet man das Einerkomplement - also (1001)2 - und addiert 1. Man erhält also als Zweierkomplementdarstellung der Zahl (-6)10 die Binärdarstellung (1010)2. Addition von Zweierkomplementzahlen Da das Bilden des Negativen einer Zahl so einfach ist, kann man die Subtraktion auf eine Negation mit anschließender Addition zurückführen. Um z.B. (2-6) zu berechnen, addieren wir einfach 2 + (-6). Das sieht binär so aus: 0010 || = (2)10 + 1010 || Zweierkomplement von ( -6)10 (s.o.) 11 --------1100 Das erste Bit des errechneten Ergebnisses zeigt uns an, dass es sich um eine negative Zahl handelt. Ihren Betrag finden wir, indem wir erneut das Zweierkomplement bilden, also zunächst die einzelnen Bits vertauschen (Einerkomplement) und dann 1 addieren: Einerkomplement von 1100 = 0011 Zweierkomplement --> 0011 + 0001 = 01002 = 410 Zusammen mit der Vorzeicheninformation von eben erhalten wir als Ergebnis der Rechnung also (-4)10 Prinzipiell kann man beliebige Zahlenformate vereinbaren, in der Praxis werden fast ausschließlich Zahlenformate mit 8, 16, 32 oder 64 Bits eingesetzt. In den meisten Programmiersprachen gibt es vordefinierte ganzzahlige Datentypen mit unterschiedlichen Wertebereichen. Je größer das Format, desto größer ist natürlich der erfasste Zahlenbereich. Einige typische Formate sind z.B.: Wertebereich 7 Bytes Java C++ 8 Bit byte char 7 -2 ... 2 -1 oder -128 ... 127 -215 ... 215-1 oder 16 Bit short int/short -32.768 ... 32.767 -231 ... 231-1 oder 32 Bit int int/long 64 Bit long ---- -2.147.483.648 ... 2.147.483.647 -263 ... 263-1 oder -9.223.372.036.854.775.808 ... 9.223.372.036.854.775.807 12 3.2 Darstellung rationaler und reeller Zahlen 3.2.1 Festkommazahlen Eine Festkommazahl ist eine Zahl, die aus einer festen Anzahl von Ziffern besteht. Die Position des Dezimalkommas ist dabei fest vorgegeben, daher der Name. Der Grundgedanke hinter Festkommazahlen ist die exakte Darstellung ohne Rundungsfehler eines Ausschnitts der rationalen Zahlen. Üblicherweise sind per Definition die ersten n kleiner/gleich k Stellen Vorkommastellen und die restlichen m = k − n Nachkommastellen. Aufgrund der exakten Darstellung ist die Menge aller Festkommazahlen einer vorgegebenen Länge k im Vergleich zu den Gleitkommazahlen sehr gering. Durch die feste Position des Dezimalkommas fällt Rechenaufwand im Vergleich zur Rechnung mit Gleitkommazahlen weg. Wird in einem Computerprogramm eine binäre Festkommadarstellung gewählt, können zudem die zur Umrechnung und Korrektur notwendigen Multiplikationen und Divisionen durch schnelle Schiebeoperationen ersetzt werden. Formal: Definition einer ganzen Zahl im B-adischen Zahlensysten: N 1 n bi B i b0 B 0 ... bN 1 B N 1 i 0 Definition einer gebrochenen Zahl im B-adischen Zahlensystem n N 1 i b B i i M 1 Rechnen mit Festkommazahlen Bei der Rechnung mit Festkommazahlen wird verfahren wie bei der Rechnung mit ganzen Zahlen. Die Position des Kommas ist bei der Addition und Subtraktion nicht von Belang. Alles bisher erläuterte zur Addition und Subtraktion von Dualzahlen bleibt unverändert gültig. Bei der Multiplikation von ganzen Zahlen gilt: Das Produkt zweier N-stelligen ergibt eine 2N-stellige Zahl. Da die Größe der darstellbaren Zahlen in Computern in der Regel vorgegeben ist (typisch 16, 32 oder 64 Stellen) wählen wir als Ergebnis nur wieder die niederwertigsten N Stellen. Wenn eine der höherwertigen Stellen eine Ziffer ≠ 0 enthält, ist ein Überlauf aufgetreten, der über einen gesonderten Mechanismus abzufangen ist. 13 Für Festkommazahlen wählt man als Bezugspunkt die Stelle, an der das Komma steht. Man wählt also vom doppeltlangen Ergebnis wiederum N Stellen vor und M Stellen nach dem Komma. Alle anderen Stellen werden verworfen. Das kann genauso zu Überläufen führen wie bei der ganzzahligen Multiplikation. Zusätzlich können aber auch Nachkommastellen ausgelöscht werden, die zu weit „hinter“ dem Komma stehen, wodurch ein Teil der Genauigkeit verloren gehen kann. Wir betrachten im nachfolgenden Beispiel nur den gebrochenen Teil, denn wir wissen bereits wie wir den ganzzahligen Teil konvertieren können. Eine Möglichkeit ist folgendes Verfahren, das man „Wiederholte Multiplikation mit abschneiden“ nennt: Man multipliziert die zu konvertierende Zahl mit der Basis B. Die Stelle, die dabei vor das Komma gerät, ist die erste Ziffer der binären Darstellung. Diese subtrahiert man vom Ergebnis und bekommt wieder einen B-adischen Bruch mit einer 0 vor dem Komma. Mit diesem verfährt man genauso, usw. Beispiel: Die Dezimalzahl 0,75625 soll ins Binärsystem (Basis B=2) gewandelt werden: Da die Anzahl der zur Verfügung stehenden binären Nachkommastellen vorgegeben und damit begrenzt ist, lässt sich mit dieser Darstellung keine beliebige Genauigkeit erreichen, sondern der dezimale Wert oft nur näherungsweise erreichen. 3.2.2 BCD Bevor wir zur Gleitkommadarstellung von Zahlen kommen, soll noch eine weitere Darstellungsmöglichkeit behandelt werden, deren Name sich aus dem Begriff Binary Coded Decimals herleitet. Um eine Zahl als BCD-Zahl darzustellen, wird jede dezimale Ziffer (0 bis 9) durch jeweils 4 Bit, also ein Halbbyte (Nibble), im Dualsystem dargestellt (0000 bis 1001). Die übrigen sechs Werte, die mit 4 Bit darstellbar sind (10102 bis 11112), stellen keine gültigen BCD-Zahlen dar (Pseudotetraden). Sie werden in manchen Systemen zur Kodierung von Vorzeichen, Überträgen oder Kommata verwendet. 14 Zur Kodierung von Zahlen mit mehr als einer Dezimalziffer werden die BCDDarstellungen der einzelnen Ziffern hintereinander gesetzt (zum Beispiel wird die Zahl 2687 als 0010 0110 1000 0111, beziehungsweise ohne trennende Leerzeichen als 0010011010000111 dargestellt). Mit einem Byte (8 Bit) können also zwei Dezimalziffern dargestellt werden. Beispiel: 1234567890 im Dezimalsystem entspricht 3 5 6 7 8 9 0 1 2 4 0001 0010 0011 0100 0101 0110 01111000 1001 0000 BCD-Zahlen werden hauptsächlich in kaufmännischen Anwendungen zur Darstellung von Geldbeträgen verwendet, um die Rundungsfehler zu vermeiden, die beim sonst erforderlichen Zahlbasiswechsel in den Nachkommastellen auftreten. 15 4 Zahlendarstellung im Rechner (Fortsetzung) 4.1 Gleitkommazahlen Bisher haben wir nur ganze Zahlen betrachtet. Nun wollen wir auch reelle (gebrochene) Zahlen zulassen. Wie kann man aber 1.) das Komma darstellen, wo die beiden binären Zeichen 0 und 1 schon belegt sind? Und wie kann man 2.) einen unendlichen Zahlenbereich (zwischen zwei beliebigen reellen Zahlen liegen unendlich viele weitere reelle Zahlen!) mit endlich vielen Ziffern (Bits) so darstellen, dass ein endliches System (unser Computer) damit rechnen kann? Bei der Gleitpunktdarstellung ist die Kommastelle Bestandteil der Zahl. Dies erreicht man durch einen kleinen Kunstgriff: Die technisch wissenschaftliche Notation gibt die Kommaposition über einen Exponenten an. So kann z.B. die Zahl 3,84 auch so geschrieben werden: 1. 384 x 10-2 2. 0,0384 x 102 3. 38,4 x 10-1 Gesucht ist eine Darstellung, die folgendes leistet: Sie soll ein möglichst großes Intervall der reellen Zahlen umfassen. Ihre Genauigkeit soll bei kleinen Zahlen sehr hoch, bei großen Zahlen niedriger sein (Bei einem Betrag von 500.000€ auf dem Konto ist es relativ unwichtig, wie viel Cent hinter dem Komma stehen. Beim Versuch mit dem letzten Kleingeld eine DVB-Fahrkarte zu kaufen spielen Cents eine ungleich wichtigere Rolle.) Die Gleitpunktdarstellung erfüllt diese beiden Forderungen. Die Idee dahinter ist ganz einfach: Kleine Zahlen benötigen wenige Stellen vor dem Dezimalpunkt, so dass wir ihnen viele Stellen hinter dem Punkt und damit eine größere Genauigkeit spendieren können. Bei großen Zahlen ist es genau umgekehrt. Der Vorteil ist, dass man auf kurze und übersichtliche Weise einen sehr großen Zahlenbereich darstellen kann. Diese Darstellungsweise hat auch enorme Vorteile für die Zahlendarstellung in Computern: Hier ist man durch die Hardware auf eine oder wenige Wortgrößen (Anzahl von Bits) festgelegt, in denen ein Operand untergebracht werden muss. Würde nun nur die normale Dualdarstellung verwendet, könnte man bereits die Zahl 10 Milliarden in einem 32-Bit Wort nicht mehr darstellen. Wenn man 16 andererseits auch gebrochene Zahlen in Festkommadarstellung zulassen möchte und jeweils 16 Bit vor und 16 Bit nach dem Komma verwendet, scheitert man bereits an der Zahl 100000. Der Bereich darstellbarer Zahlen ist in diesem Falle 215 bis 215 216 Gleitpunktzahlen bestehen nach dem Gesagten also aus drei Bestandteilen: Dem Vorzeichenbit: V Dem Exponenten: E Der Mantisse: M Das Vorzeichenbit gibt an, ob die vorliegende Zahl positiv ('0') oder negativ ('1') ist. Der Exponent ist eine Binärzahl, zum Beispiel im Bereich -127 bis +127, die angibt, mit welcher Potenz einer Basiszahl b die vorliegende Zahl zu multiplizieren ist. Die Mantisse besteht aus Binärziffern m1...mn und gibt den Wert der vorliegenden Zahl an. Der Zahlenwert ergibt sich aus der Formel: Wert = Mantisse x BasisExponent wobei das Vorzeichen +1 ist, wenn V=0 ist und -1, wenn V=1 ist. Dabei wird die Mantisse als positive Dualzahl und der Exponent als Dualzahl in Zweierkomplementdarstellung interpretiert. In den obigen Beispielen haben die Gleitpunktzahlen keine einheitliche Darstellung bezüglich der Vorkommastelle. Folglich gibt es unendlich viele Darstellungsmöglichkeiten für eine Zahl! --> Zur Bildung der normierten Gleitpunktzahl muss diejenige Darstellung gefunden werden, in der das (binäre) Ergebnis eine 1 vor dem Komma führt. Normierte Gleitpunktzahlen Motivation für eine Normierung: Es soll für jede darstellbare Zahl genau eine Darstellung als Gleitpunktzahl geben. eindeutige Darstellung durch Normierung. Da durch die Normalisierung im Binärsystem immer eine 1 vor dem Komma stehen muss, kann man diese auch weglassen. 17 In der Mantisse werden dann nur noch die Stellen hinter dem Komma notiert! (Die führende "1," steht also gedacht links vor der Mantisse.) Durch die Einsparung der führenden 1 können die Bits der Mantisse optimal ausgenutzt werden, was besonders bei unendlich vielen Nachkommastellen (periodische Zahlen) eine höhere Rechengenauigkeit ermöglicht. Gleitpunktzahlen nach IEEE 754 Nach IEEE 754 (Institute of Electrical and Electronics Engineers) normierte Gleitpunktzahlen verwenden b = 2 als Basiszahl. Zwei von IEEE verabschiedete Normen werden heute in den meisten Rechnern verwendet: Short Real (einfache Genauigkeit) mit insgesamt 32 Bit: Vorzeichen - 1 Bit, Exponent - 8 Bit, Mantisse - 23 Bit Long Real (doppelte Genauigkeit) mit insgesamt 64 Bit: Vorzeichen - 1 Bit, Exponent - 11 Bit, Mantisse - 52 Bit Im Folgenden betrachten wir einige Beispiele im Short Real Format mit 32 Bit: V Exponent ---> Mantisse ------------------------------------> 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -3,7510 = 1100 0000 0111 0000 0000 0000 0000 00002 = C070000016 V Exponent ---> Mantisse ------------------------------------> 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3,7510 = 0100 0000 0111 0000 0000 0000 0000 00002 = 4070000016 Rechenfehler mit Gleitpunktzahlen Dezimale Gleitpunktzahlen und binäre Gleitpunktzahlen kann man ineinander umrechnen. Allerdings geht dieser Umrechnungsvorgang in beiden Richtungen nicht immer auf, wenn wir jeweils eine bestimmte Anzahl von Ziffern für die Mantisse vorschreiben (also die Genauigkeit einer Zahl begrenzen, indem wir die folgenden Stellen 18 abschneiden). So lässt sich zum Beispiel die dezimale Zahl 0,1 nicht exakt durch eine 32-BitGleitpunktzahl darstellen, wie das folgende Beispiel zeigt: V Exponent ---> Mantisse ------------------------------------> 0 0 1 1 1 1 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0,110 ≈ 0011 1101 1100 1100 1100 1100 1100 11012 = 3DCCCCCD16 (Im 64-Bit-Format mit doppelter Genauigkeit sieht man, dass der Wert der Zahl eigentlich = 0,10000000149011612 ist) V Exponent ---> Mantisse ------------------------------------> 0 0 1 1 1 1 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0,110 ≈ 0011 1101 1100 1100 1100 1100 1100 11002 = 3DCCCCCC16 (Im 64-Bit-Format mit doppelter Genauigkeit sieht man, dass der Wert der Zahl eigentlich = 0,09999999403953552 ist) Wertebereiche reeller Zahlen in Programmiersprachen Wertebereich 38 38 -3,4x10 bis +3,4x10 308 -1,7x10 bis +1,7x10 308 Bit Java C++ 32 float float 64 double double Konvertierung reeller Zahlen in 32-Bit IEEE 754 Gleitpunktzahlen Zunächst das generelle methodische Vorgehen: 1. Das Vorzeichen wird mit 0 für positive Zahlen und 1 für negative Zahlen codiert. 2. Konvertierung des ganzzahligen Anteils 3. Der gebrochene Anteil wird sukzessive mit 2 multipliziert. Wenn das Ergebnis größer (oder gleich) 1 ist, wird 1 subtrahiert und eine 1 als Ergebnis notiert. Wenn das Ergebnis kleiner als 1 ist, wird erneut mit 2 multipliziert und eine 0 als Ergebnis notiert. Diese Berechnung wird solange wiederholt, bis das Ergebnis gleich 0 ist. (Achtung! Dieser Prozess kann unendlich lange fortschreiten. Die Genauigkeit der Berechnung wird durch die für die Mantisse verfügbare Anzahl der Stellen begrenzt!) 4. Das Ergebnis wird als Festkomma-Zahl notiert. 19 5. Die Festkomma-Zahl wird normalisiert, d.h. das Komma wird so weit nach rechts oder links verschoben, bis vor dem Komma eine 1 steht. 6. Die Anzahl der Stellen, um die das Komma verschoben wird, ergibt den Wert des Exponenten. 7. Wird das Komma nach rechts verschoben, ist der Exponent negativ, wird er nach links verschoben, ist der Exponent positiv. 8. Der Exponent e wird als natürliche Zahl e' codiert mit Wert e' = e + 127 (Zum Exponenten addiert man einen sog. Bias von 127 und speichert das Ergebnis als vorzeichenlose 8-Bitzahl. Dies ist eine weitere Methode, um positive und negative Zahlen darzustellen. Sie wird im Falle von Gleitpunktzahlen angewendet, um Vergleiche zwischen verschiedenen Gleitpunktzahlen technisch besonders einfach zu machen.) 9. Die Nachkommastellen (!) werden genommen und auf die Breite der Mantisse nach rechts mit Nullen aufgefüllt. 10. Die Bits werden in der Reihenfolge Vorzeichen - Exponent - Mantisse angeordnet. Die Konvertierung am Beispiel Beispiel: Konvertierung von (-3.75)10 in eine Gleitpunktzahl: 1. Vorzeichen: 1 2. 3 = (11)2 3. 0.75 * 2 = 1.5 1.5 - 1 = 0.5 --> 1 als Ergebnis notieren. 0.5 * 2 = 1 1 - 1 = 0 --> 1 als Ergebnis notieren. 4. Festkomma-Darstellung: (11.11)2 5. Normalisieren: 1.111 * 21 Da die erste Ziffer immer 1 ist, fällt diese nach der Normalisierung weg! 6. Exponent: 1 --> e' = 1 + 127 = 128 = (1000 0000)2 7. Die Nachkommastellen der Mantisse m mit Nullen auffüllen: m = (111 0000 0000 0000 0000 0000)2 8. Das Ergebnis: 1100 0000 0111 0000 0000 0000 0000 0000 Gleitkomma-Arithmetik Die Multiplikation von Gleitkommazahlen ist einfach, denn es gilt laut den Potenzgesetzen: e1 e2 e1 e 2 1 2 1 2 m 2 m 2 m m 2 20 Das bedeutet, dass die Mantissen als normale Dualzahlen multipliziert werden können und die Exponenten addiert werden. Das gleiche gilt für die Division. Schwieriger ist dagegen die Addition: Hier muss zunächst dafür gesorgt werden, dass die Exponenten angeglichen werden, denn eine Addition der Mantissen kann entsprechend den Potenzgesetzen nur dann richtig ausgeführt werden, wenn die Exponenten gleich sind: m1 2e1 m2 2e1 m1 m2 2e1 Zu diesem Zweck muss zunächst ermittelt werden, welcher Exponent der größere ist und die Exponentendifferenz d wird mittels einer Subtraktion gebildet. Sodann wird die Mantisse der Zahl mit dem kleineren Exponenten um d Stellen nach rechts verschoben, wobei von links Nullen nachgezogen werden. Dies entspricht einer Division der Mantisse durch 2d bei gleichzeitiger Vergrößerung des Exponenten um d. Nun kann die Addition auf den angepassten Mantissen durchgeführt werden, wobei der größere Exponent der Operanden zum Exponenten des Ergebnisses wird. Durch die Addition kann es passieren, dass im Ergebnis eine Folge von führenden Nullen entsteht. Um aber für nachfolgende Operationen die Genauigkeit nicht einzuschränken, wird die Mantisse des Ergebnisses nun wieder nach links verschoben, bis die erste signifikante Stelle eine 1 ist. Wenn die Verschiebedistanz d’ ist, muss schließlich der Exponent noch um d’ vermindert werden, damit der Wert des Ergebnisses nicht verändert wird. 21 5 Computerorganisation / Schaltalgebra (Boolesche Algebra) Computerorganisation Literatur: - Tanenbaum, Andrew S./Goodman, James: Computerarchitektur - Gumm, Hans-Peter; Sommer, Manfred: Einführung in die Informatik Einleitung Ein digitaler Computer ist eine Maschine, die Probleme für Personen dadurch lösen kann, daß sie Instruktionen ausführt, die sie von ihnen erhalten hat. Eine Reihe von Instruktionen, die beschreiben, wie eine bestimmte Aufgabe auszuführen ist, nennt man Programm. Die elektronischen Schaltungen eines Computers können eine begrenzte Menge einfacher Instruktionen erkennen, in die alle Programme konvertiert werden müssen, ehe sie ausgeführt werden können. Diese grundlegenden Instruktionen sind selten komplizierter als beispielsweise: o o o Addiere 2 Zahlen. Prüfe eine Zahl, um festzustellen, ob sie Null ist. Kopiere einen Datenteil von einem Speicherbereich des Computers in einen anderen. Insgesamt betrachtet, bilden die primitiven Instruktionen eines Computers die so genannte Maschinensprache (Machine Language). Personen, die einen neuen Computer entwerfen, müssen entscheiden, welche primitiven Instruktionen in seine Maschinensprache einzubeziehen sind. Normalerweise versuchen sie, die primitiven Instruktionen so einfach wie möglich zu halten, um die Komplexität und somit die Kosten der erforderlichen Elektronik zu reduzieren. Da die meisten Maschinensprachen derart einfach sind (Folgen von Nullen und Einsen!), lassen sie sich von Personen nur mit Schwierigkeiten benutzen. Dies hat im Laufe der Zeit zur Strukturierung von Computern als Reihe von Abstraktionen geführt. Dabei baut jede Abstraktion auf der jeweils darunterliegenden auf. Auf diese Weise kann die Komplexität gemeistert werden, und Computersysteme lassen sich systematisch und organisiert entwickeln. Wir nennen diese Methode strukturierte Computerorganisation (Structured Computer Organization). 22 Strukturierte Computerorganisation Wie bereits gesagt, besteht zwischen dem, was für Menschen, und dem, was für Computer bequem ist, ein Riesenunterschied. Leute möchten X, während der Computer nur Y schafft. Das führt zu einem Problem. Dieses Problem kann auf zweierlei Weise angegangen werden. Beide Methoden betreffen das Design einer neuen Instruktionsmenge, die sich von Menschen leichter als die eingebauten Maschineninstruktionen benutzen läßt. Insgesamt bilden diese neuen Instruktionen auch eine Sprache, die wir L1 nennen, ebenso wie die eingebauten Maschineninstruktionen eine Sprache bilden, die wir L0 nennen. Die beiden Ansätze unterscheiden sich in der Ausführung der in L1 geschriebenen Programme von einem Computer, der doch nur Programme ausführen kann, die in seiner Maschinensprache - L0 - geschrieben wurden. 1. Bei der ersten Methode, ein in L1 geschriebenes Programm auszuführen, wird jede in ihm enthaltene Instruktion zuerst durch eine entsprechende Folge von Instruktionen in L0 ersetzt. Das daraus resultierende Programm besteht gänzlich aus L0-Instruktionen. Der Computer führt dann statt des alten L1-Programms das neue L0Programm aus. Diese Technik heißt Übersetzung (Translation). 2. Bei der zweiten Methode wird ein Programm in L0 geschrieben, das in L1 geschriebene Programme als Eingabedaten übernimmt und sie ausführt, indem alle Instruktionen nacheinander geprüft und direkt als entsprechende Folge von L0-Instruktionen ausgeführt werden. Diese Technik, bei der zunächst kein neues Programm in L0 erzeugt werden muss, heißt Interpretation, und das auszuführende Programm wird Interpreter genannt. Übersetzung und Interpretation ähneln sich. Bei beiden Methoden werden die in L1 geschriebenen Instruktionen letztlich abgearbeitet, indem entsprechende Folgen von L0-Instruktionen ausgeführt werden. Der Unterschied besteht darin: Bei der Übersetzung wird zuerst das gesamte L1-Programm in ein L0Programm konvertiert, das L1-Programm weggeworfen und das neue L0Programm in den Computerspeicher geladen und ausgeführt wird. Zur Ausführungszeit läuft das neu generierte L0-Programm im Computer und steuert diesen. Bei der Interpretation wird jede L1-Anweisung nach der Prüfung und Dekodierung unmittelbar ausgeführt. Es wird kein übersetztes Programm generiert. Hier hat der Interpreter die Kontrolle über den Computer. 23 Für den Computer ist das L1-Programm nichts weiter als eine Ansammlung von Daten. In der Praxis werden beide Methoden und vermehrt auch eine Kombination von beiden angewandt. Sprachen und Ebenen Bequemer als das Konzept der Übersetzung und Interpretation ist die Vostellung, wir hätten es mit einem hypothetischen Computer oder einer virtuellen Maschine (Virtual Machine) zu tun, deren Maschinensprache L1 ist. Wir nennen diese virtuelle Maschine M1 (und die virtuelle Maschine, die L0 entspricht, nennen wir M0). Könnte man eine solche Maschine kostengünstig genug produzieren, bestünde für L1 oder eine virtuelle Maschine, die L1-Programme ausführt, überhaupt keine Notwendigkeit. Man könnte ganz einfach ihre Programme in L1 schreiben und sie vom Computer direkt ausführen lassen. Man könnte aber trotzdem Programme für die virtuelle Maschine schreiben, deren Sprache L1 ist, auch wenn es zu teuer oder zu kompliziert wäre, sie mit elektronischen Schaltungen zu bauen. Diese Programme können von einem in L1 geschriebenen Programm interpretiert oder übersetzt werden, das selbst direkt vom vorhandenen Computer ausgeführt werden kann. Anders ausgedrückt: Die Menschen können Programme für virtuelle Maschinen so schreiben, als würden solche Maschinen wirklich existieren. Die Erfindung einer ganzen Reihe von Sprachen, von denen jede ein bißchen bequemer ist als ihre Vorgängerin, kann man endlos fortsetzen, bis man endlich eine geeignete erreicht hat. Jede Sprache benutzt ihre Vorgängerin als Grundlage, so daß wir einen Computer, der diese Technik benutzt, als Reihe von Schichten (Layers) oder Ebenen (Levels) betrachten können, die aufeinander aufbauen. Die unterste Sprache bzw. Ebene ist die einfachste und die höchste die ausgefeilteste. 24 Die meisten modernen Computer bestehen aus mehreren Ebenen. In dem hier gezeigten Modell ist die Ebene 0 ganz unten die wahre Hardware der Maschine. Ihre Schaltungen führen die Maschinenspracheprogramme der Ebene 1 aus. Der Vollständigkeit halber sei erwähnt, daß es unter unserer Ebene 0 noch eine andere gibt. Diese Ebene fällt in das Hoheitsgebiet der Elektrotechnik und liegt damit außerhalb der für dieses Seminar interessanten Themen. Sie heißt Geräteabene (Device Level). Auf ihr sieht der Designer die einzelnen Transistoren - die Primitiven der untersten Ebene aus Sicht des Computer-Designers. Fragt einer, was sich im Inneren von Transistoren abspielt, berührt er das Gebiet der Festkörperphysik. Ebene 0 - Die digitale Logik Auf Ebene 0 - der Ebene der digitalen Logik - heißen die uns interessierenden Objekte Gatter. Diese Gatter werden zwar aus analogen Komponentengebaut, wie etwa Transistoren, können aber präzise als digitale Geräte modelliert werden. Jedes Gatter hat einen oder mehrere digitale Eingänge (die Signale stellen 0 oder 1 dar), und jedes berechnet aus diesen Eingängen mittels einer einfachen Funktion, beispielsweise AND oder OR, eine Ausgabe. 25 Jedes Gatter setzt sich mindestens aus einer Handvoll Transistoren zusammen. Aus einer kleinen Anzahl von Gattern kann ein 1-Bit-Speicher gebildet werden, der eine 0 oder eine 1 speichern kann. Mehrere 1-Bit-Speicher (z.B. 16, 32 oder 64) können zu Registern gruppiert werden. Jedes Register kann von einer einzigen bis zu einer bestimmten maximalen Anzahl Binärzahlen aufnehmen. Gatter lassen sich auch so kombinieren, daß man mit ihnen direkt die Hauptrechenmaschine (ALU) bilden kann. Ebene 1 - die Mikroarchitektur Als nächstes kommt die Mikroarchitekturebene. Auf dieser Ebene befindet sich eine Gruppe von (üblicherweise) 8 bis 32 Registern, die einen lokalen Speicher und eine Schaltung bilden, die man ALU nennt. Die ALU kann einfache arithmetische Operationen durchführen. Die Register sind mit der ALU verbunden. Dies ist der Datenweg, über den die Daten fließen. Wie die Daten verarbeitet werden, beschreibt der von-Neumann-Zyklus. Ebene 2 - Die ISA-Ebene (Instruction Set Architecture) Die Ebene 2 nennen wir ISA-Ebene. Jeder Computer-Hersteller veröffentlicht ein Handbuch für jeden von ihm verkauften Computer. Diese Handbücher behandeln die ISA-Ebene und nicht die ihr zugrundeliegenden Ebenen darunter. Die in diesen Handbüchern enthaltene Beschreibung der Instruktionsmenge der Maschine betrifft in Wirklichkeit die Instruktionen, die vom Mikroprogramm oder von Hardware-Schaltungen interpretativ ausgeführt werden (z.B. SSE 1-3, MMX, oder 3Dnow!). Ebene 3 - Die Betriebssystemmaschine Die Ebene 3 ist eine hybride Ebene. Die meisten Instruktionen in ihrer Sprache befinden sich auch auf der ISA-Ebene. Außerdem gibt es dort eine Reihe neuer Instruktionen, eine andere Speicherorganisation, die Möglichkeit, zwei oder mehr Programme gleichzeitig auszuführen, und verschiedene andere Merkmale. Diese auf Ebene 3 neu hinzukoemmenden Merkmale werden von einem Interpreter ausgeführt, der auf Ebene 2 läuft. Historisch ist dies das Betriebssystem. Diese Anweisungen der Ebene 3, die mit denen der Ebene 2 identisch sind, werden direkt vom Mikroprogramm (bzw. von festverdrahteten Hardwareschaltungen) und nicht vom Betriebssystem ausgeführt. Anders ausgedrückt, einige Anweisungen der Ebene 3 werden vom Betriebssystem und andere direkt vom Mikroprogramm (z.B. vom BIOS) interpretiert. Das ist mit "hybrid" gemeint. Wir nennen dies die Ebene der Betriebssystemmaschine. 26 Ebene 4 - Assemblersprache Die Ebene 4, diejenige der Assemblersprache, ist eigentlich die symbolische Form einer der zugrundeliegenden Sprachen. Diese Ebene bietet die Möglichkeit, Programme für die Ebenen 1, 2 und 3 im Vergleich zu den Sprachen der jeweiligen Ebene etwas angenehmer zu gestalten. Programme in Assemblersprache werden zuerst in die Sprache der Ebene 1, 2 oder 3 übersetzt und dann von der geeigneten virtuellen oder physischen Maschine interpretiert. Das Programm, das die Übersetzung ausführt, ist ein Assembler. Ebene 5 - Hochsprachen Die Ebene 5 befasst sich normalerweise mit einer Sprache, die auf die Verwendung durch Anwendungsprogrammierer ausgerichtet wurde, die bestimmte Probleme lösen müssen. Eine solche Sprache ist eine sogenannte Hochsprache. Davon gibt es praktisch Hunderte. Ein paar bekannte sind Basic, C, C++, Java, LISP und Prolog. Die in diesen Sprachen geschriebenen Programme werden allgemein von Übersetzern in die Ebene 3 oder 4 übersetzt. Diese Übersetzer nennt man Compiler, obwohl die Programme gelegentlich auch interpretiert werden. Beispielsweise werden in Java geschriebene Programme oft interpretiert. Die digitale logische Ebene Die unterste Ebene der im letzten Abschnitt gezeigten Hierarchie ist die digitale logische Ebene - die echte Computerhardware. Die Grundelemente, aus denen alle digitalen Computer gebaut werden, sind erstaunlich einfach. Digitale Schaltungen lassen sich aus einer kleinen Zahl von primitiven Elementen bauen, indem man diese auf vielfache Art und Weise kombiniert. Im Folgenden werden diese primitiven Elemente beschrieben. Gatter Bei einer digitalen Schaltung gibt es nur zwei logische Werte. Normalerweise stellt ein Signal zwischen 0 und 1 Volt einen Wert (z.B. eine binäre 0) und ein Signal zwischen 2 und 5 Volt einen anderen Wert (z.B. eine binäre 1) dar. Spannungen außerhalb dieser beiden Bereiche sind nicht zulässig. Winzige elektronische Geräte namens Gatter (eengl. gates) können mit diesen zweiwertigen Signalen verschiedene Funktionen berechnen. Diese Gatter bilden die Hardware-Grundlage, auf der alle digitalen Computer basieren. 27 Die Einzelheiten darüber, wie diese Gatter im Inneren funktionieren, sind nicht Gegenstand dieses Seminars, sondern gehören zur Geräteebene, die direkt unter unserer Ebene 0 liegt! Wir schweifen jetzt aber dennoch kurz ab und werfen einen kurzen Blick auf das einfache - Grundkonzept. Jede moderne digitale Logik beruht letztendlich auf der Tatsache, daß ein Transistor so gebaut werden kann, daß er als sehr schneller, binärer Schalter arbeitet. In der folgenden Abb. (a) ist ein einzelner bipolarer Transistor (der Kreis) in eine einfache Schaltung eingebettet. Abb (a): Transistor-Inverter Dieser Transistor hat drei Verbindungen mit der Außenwelt: den Kollektor (Drain), die Basis (Gate) und den Emitter (Source). Liegt die Eingangsspannung Vin unter einem bestimmten kritischen Wert, schaltet sich der Transistor aus und verhält sich wie ein unendlicher Widerstand. Dies veranlaßt den Ausgang der Schaltung Vout, einen Wert nahe Vcc (eine extern geregelte Spannung) anzunehmen, die normalerweise bei diesem Transistortyp bei +5 Volt liegt. Überschreitet Vin den kritischen Wert, schaltet sich der Transistor ein und funktioniert wie ein Draht, wodurch Vout nach unten zur Masse (gemäß Konvention 0 Volt = kein Strom) geschaltet wird. Wichtig dabei ist folgendes: Wenn Vin auf Low liegt, liegt Vout auf High und umgekehrt. Folglich ist diese Schaltung ein Inverter, der eine logische 0 in einer logische 1 und eine logische 1 in eine logische 0 konvertiert. Der Widerstand (Resistor) - die gezackte Linie - ist nötig, um den vom Transistor gezogenen Strom zu begrenzen. Die Zeit, die benötigt wird, um von einem Zustand in den anderen umzuschalten, beträgt normalerweise ein paar Nanosekunden. 28 Abb. (b) zeigt zwei in Reihe geschaltete Transistoren. Liegen V1 und V2 auf High, leiten beide Transistoren, und Vout wird nach unten zur Masse (0 Volt) geschaltet. Liegt einer der beiden Eingänge auf Low, schaltet der entsprechende Transistor aus und der Ausgang geht auf High. Anders ausgedrückt: Vout ist auf Low, aber nur dann, wenn sowohl V1 als auch V2 auf High liegen. Abb. (c) zeigt zwei parallel geschaltete Transistoren. Liegt einer der Eingänge in dieser Konfiguration auf High, schaltet der der entsprechende Transistor ein und zieht den Ausgang nach unten zur Masse. Sind beide Eingänge auf Low, bleibt der Ausgang auf High. Diese drei Schaltungen bilden die drei einfachsten Gatter. Sie heißen NOT, NAND und NOR. NOT-Gatter nennt man oft Inverter. Wir benutzen die beiden Begriffe als Synonyme. Wenden wir nun die Konvention an, dass High (Vcc Volt) eine logische 1 und Low (Masse) eine logische 0 ist, können wir den Ausgangswert als Funktion der Eingangswerte ausdrücken. Gatter sind die grundlegenden Bausteine der digitalen logischen Ebene. Aus den vorhergehenden Darstellungen wird klar, dass das NAND- und NOR-Gatter je zwei Transistoren benötigen, während das AND- und OR-Gatter jeweils drei Transistoren braucht. Aus diesem Grund basieren viele Computer auf NAND- und NOR-Gattern und nicht auf den bekannteren AND- und OR-Gattern. 29 Die nachfolgende Übersicht zeigt die wesentlichen Logikgatter in DIN-Darstellung sowie die dazugehörigen Wertetabellen. Die Boolesche Algebra Um die Schaltungen zu beschreiben, die durch Kombination von Gattern gebaut werden können, ist eine Algebra erforderlich, bei der Variablen und Funktionen nur die Werte 0 und 1 annehmen können. Eine solche Algebra nennt man boolesche Algebra nach ihrem Begründer, dem englischen Mathematiker George Boole (1815-1864). Da eine boolesche Funktion mit n Variablen nur 2n mögliche Kombinationen von Eingabewerten hat, kann man die Funktion vollständig beschreiben, indem man eine Tabelle mit 2n Reihen angibt, wobei jede Reihe den Wert der Funktion für eine andere Kombination von Eingangswerten angibt. Eine solche Tabelle heißt Wahrheitstabelle. Wollen wir uns darauf festlegen, die Reihen einer Wahrheitstabelle immer in numerischer Reihenfolge (zur Basis 2) anzuordnen, ergibt für zwei Variablen die Reihenfolge 00, 01, 10 und 11. Die Funktion kann also vollständig mit der 2n-Bit-Binärzahl beschrieben werden, die wir erhalten, wenn wir die Ergebnisspalte der Wahrheitstabelle vertikal lesen. Das heißt: NAND ist 1110, NOR ist 1000, AND ist 0001 und OR ist 0111. Arithmetische Schaltungen Ein Computer, der keine arithmetischen Operationen durchführen kann, wäre undenkbar. Folglich sind Schaltungen zur Durchführung von Addition, Multiplikation, usw. ein unentbehrlicher Teil jeder CPU. Als Beispiel wenden wir uns der Betrachtung von Schaltungen für die Addition zu, da diese die zentralen Bausteine in Rechnern darstellen 30 Halbaddierer Ein Halbaddierer ist eine Schaltung, die mit n Eingängen die Summe aus n Binärzahlen und den daraus resultierenden Übertrag berechnen kann. Sie enthält zwei Ausgänge, einen für die berechnete Summe und einen weiteren für den Übertrag zur nächsten Stelle (nach links). Als Beispiel betrachten wir den kleinstmöglichen Halbaddierer, d.h. eine Schaltung, die zwei Binärzahlen x und y addieren soll. An den Eingängen x und y liegen die zu addierenden Binärzahlen, am Ausgang s entsteht das Summenbit und am Ausgang c der Übertrag (engl. carry): Die Summe ergibt sich also aus (A XOR B) und der Übertrag resultiert aus (A AND B). Volladdierer Nun ist ein Halbaddierer zwar für die Addition der niederwertigen Binärzahlen geeignet, reicht aber nicht aus, um den Übertrag von rechts durchzuführen. Hier wird ein Volladdierer benötigt. Der Volladdierer muss nicht nur die Ausgänge s (Summe) und cout (Carry out), sondern neben den zwei Eingängen A und B auch den Eingang cin (Carry in) für den Übertrag von der rechten Position bereitstellen. Auf Schaltungsebene muss ein Volladdierer also aus zwei Halbaddierern und einem OR-Gatter bestehen: Die Ausgangsleitung Summe ist 1, wenn eine ungerade Zahl von A, B, und Carry in 1 sind. Carry out ist 1, wenn entweder A und B beide 1 sind (linker Eingang zum OR-Gate) oder eine davon 1 und das Carry-in-Bit ebenfalls 1 ist. Zusammen erzeugen die beiden Halbaddierer sowohl die Summen- als auch die Übertragsbits. Mit einer Kaskade von n-1 Volladdierern und einem Halbaddierer kann man ein Addierwerk erstellen, das n-stellige Binärzahlen addieren kann. Jeder 1-Bit Addierer ist für eine Stellenposition verantwortlich. 31 32