Wie kann man eine 80-Bit-Gleitkommazahl verwalten, da ein 32-Bit-System keine 2 ^ 33-Zahl verwalten kann (aufgrund der offensichtlichen 32-Bit-Grenze) ?
Es sollte "80-Bit" erfordern ...
Wie kann man eine 80-Bit-Gleitkommazahl verwalten, da ein 32-Bit-System keine 2 ^ 33-Zahl verwalten kann (aufgrund der offensichtlichen 32-Bit-Grenze) ?
Es sollte "80-Bit" erfordern ...
Antworten:
Eine der Bedeutungen einer 32-Bit-CPU ist, dass ihre Register 32 Bit breit sind. Dies bedeutet nicht, dass es nicht mit 64-Bit-Zahlen umgehen kann, nur, dass es zuerst mit der unteren 32-Bit-Hälfte und dann mit der oberen 32-Bit-Hälfte der Sekunde umgehen muss. (Aus diesem Grund haben CPUs ein Übertragsflag .) Es ist langsamer als wenn die CPU die Werte nur in ein breiteres 64-Bit-Register laden könnte, aber immer noch möglich.
Daher beschränkt die "Bit-Größe" eines Systems nicht unbedingt die Größe der Zahlen, mit denen ein Programm umgehen kann, da Sie Operationen, die nicht in CPU-Register passen, immer in mehrere Operationen aufteilen können. Auf diese Weise werden Vorgänge langsamer, verbrauchen mehr Speicher (wenn Sie Speicher als "Notizblock" verwenden müssen) und sind schwieriger zu programmieren, die Vorgänge sind jedoch weiterhin möglich.
Bei Intel 32-Bit-Prozessoren und Fließkomma-Prozessoren spielt dies jedoch keine Rolle, da der Fließkomma-Teil der CPU über eigene Register verfügt und diese 80 Bit breit sind. (Zu Beginn der x86-Geschichte war die Gleitkommafunktion ein separater Chip, der ab 80486DX in die CPU integriert wurde.)
@ Breakthroughs Antwort hat mich dazu inspiriert, dies hinzuzufügen.
Gleitkommawerte funktionieren, sofern sie in den FPU-Registern gespeichert sind, sehr anders als binäre Ganzzahlwerte.
Die 80 Bits eines Gleitkommawertes werden auf eine Mantisse und einen Exponenten aufgeteilt (es gibt auch die "Basis" in Gleitkommazahlen, die immer 2 ist). Die Mantisse enthält die signifikanten Ziffern, und der Exponent bestimmt, wie groß diese signifikanten Ziffern sind. Es gibt also keinen "Überlauf" in ein anderes Register. Wenn Ihre Zahl zu groß wird, um in die Mantisse zu passen, steigt Ihr Exponent und Sie verlieren an Genauigkeit. Aus diesem Grund wird es Gleitkomma genannt.
Wenn Ihr Exponent zu groß ist, haben Sie einen Gleitkommaüberlauf, können ihn jedoch nicht einfach auf ein anderes Register erweitern, da Exponent und Mantisse miteinander verknüpft sind.
Ich könnte in einigen Dingen ungenau und falsch liegen, aber ich glaube, das ist das Wesentliche. (Dieser Wikipedia-Artikel illustriert das Obige etwas prägnanter.)
Es ist in Ordnung, dass dies völlig anders funktioniert, da der gesamte "Gleitkomma" -Teil der CPU eine Art eigene Welt ist - Sie verwenden spezielle CPU-Anweisungen, um darauf zuzugreifen, und so weiter. Auch im Hinblick auf den Punkt der Frage ist die Bit-Qualität der FPU nicht eng mit der Bit-Qualität der nativen CPU gekoppelt, da sie separat ist.
-fomit-frame-pointer
dieses Register zurückbekommen.
32-Bit, 64-Bit und 128-Bit beziehen sich alle auf die Wortlänge des Prozessors, die als "grundlegender Datentyp" angesehen werden kann. Häufig ist dies die Anzahl der Bits, die zum / vom RAM des Systems übertragen werden, und die Breite der Zeiger (obwohl nichts Sie daran hindert, Software zu verwenden, um auf mehr RAM zuzugreifen, als ein einzelner Zeiger zugreifen kann).
Unter der Annahme einer konstanten Taktrate (und alles andere in der Architektur ist konstant) und der Annahme, dass Lese- / Schreibvorgänge im Speicher dieselbe Geschwindigkeit haben (wir nehmen hier einen Taktzyklus an, aber dies ist im wirklichen Leben weit davon entfernt), können Sie dies Fügen Sie zwei 64-Bit-Zahlen in einem einzigen Taktzyklus auf einem 64-Bit-Computer hinzu (drei, wenn Sie das Abrufen der Zahlen aus dem RAM zählen):
ADDA [NUM1], [NUM2]
STAA [RESULT]
Wir können die gleiche Berechnung auch auf einem 32-Bit-Computer durchführen ... Auf einem 32-Bit-Computer müssen wir dies jedoch in der Software tun, da die unteren 32-Bit-Werte zuerst addiert werden müssen, um den Überlauf zu kompensieren und dann zu addieren die oberen 64-Bit:
ADDA [NUM1_LOWER], [NUM2_LOWER]
STAA [RESULT_LOWER]
CLRA ; I'm assuming the condition flags are not modified by this.
BRNO CMPS ; Branch to CMPS if there was no overflow.
ADDA #1 ; If there was overflow, compensate the value of A.
CMPS ADDA [NUM1_UPPER], [NUM2_UPPER]
STAA [RESULT_UPPER]
Anhand meiner erfundenen Assemblersyntax können Sie leicht erkennen, wie lange Operationen mit höherer Genauigkeit auf einer Maschine mit geringerer Wortlänge exponentiell dauern können. Dies ist der eigentliche Schlüssel für 64-Bit- und 128-Bit-Prozessoren: Sie ermöglichen es uns, eine größere Anzahl von Bits in einer einzigen Operation zu verarbeiten. Einige Maschinen enthalten Anweisungen zum Hinzufügen anderer Mengen mit einem Übertrag (z. B. ADC
auf x86), das obige Beispiel berücksichtigt jedoch beliebige Genauigkeitswerte.
Um dies auf die Frage zu erweitern, ist es einfach zu sehen, wie wir Zahlen hinzufügen können, die größer als die verfügbaren Register sind. Wir teilen das Problem einfach in Teile auf, die so groß wie die Register sind, und arbeiten von dort aus. Obwohl, wie von @MatteoItalia erwähnt , der x87-FPU-Stapel native Unterstützung für 80-Bit-Mengen bietet, müssen in Systemen, die diese Unterstützung nicht bieten (oder Prozessoren, denen eine Gleitkommaeinheit vollständig fehlt!), Die entsprechenden Berechnungen / Operationen in Software ausgeführt werden .
Für eine 80-Bit-Zahl würde man nach dem Hinzufügen jedes 32-Bit-Segments auch auf einen Überlauf in das 81. Bit prüfen und optional die höherwertigen Bits auf Null setzen. Diese Überprüfungen / Nullen werden automatisch für bestimmte x86- und x86-64-Befehle ausgeführt, bei denen die Quell- und Zieloperandengrößen angegeben werden (obwohl diese nur in Potenzen von 2 angegeben werden, beginnend mit 1 Byte Breite).
Natürlich kann man bei Gleitkommazahlen die Binäraddition nicht einfach durchführen, da die Mantisse und die signifikanten Ziffern in versetzter Form zusammengepackt sind. In der ALU auf einem x86-Prozessor gibt es eine Hardwareschaltung, um dies für IEEE 32-Bit- und 64-Bit-Floats durchzuführen. aber auch in Abwesenheit einer Gleitkommaeinheit (FPU) können die gleichen Berechnungen in Software durchgeführt werden (zB durch die Verwendung der GNU Scientific - Bibliothek , die eine FPU verwendet , wenn sie mit auf Architekturen kompiliert, zurück zu Softwarealgorithmen fallen wenn keine Gleitkomma-Hardware verfügbar ist (zB für eingebettete Mikrocontroller ohne FPUs).
Wenn genügend Speicherplatz vorhanden ist, können auch Berechnungen mit einer willkürlichen (oder "unendlichen" - innerhalb realistischer Grenzen) Genauigkeit durchgeführt werden, wobei mehr Speicherplatz benötigt wird, wenn mehr Genauigkeit erforderlich ist. Eine Implementierung davon gibt es in der GNU Multiple Precision-Bibliothek , die unbegrenzte Präzision (bis Ihr RAM natürlich voll ist) für Integer-, Rational- und Gleitkomma-Operationen ermöglicht.
Aufgrund der Speicherarchitektur des Systems können Sie möglicherweise nur 32 Bit gleichzeitig verschieben. Dies hindert Sie jedoch nicht daran, größere Zahlen zu verwenden.
Denken Sie an Multiplikation. Sie kennen Ihre Multiplikationstabellen vielleicht bis zu 10x10, haben aber wahrscheinlich kein Problem damit, 123x321 auf einem Blatt Papier auszuführen: Sie teilen es einfach in viele kleine Probleme auf, multiplizieren einzelne Ziffern und kümmern sich um den Transport usw.
Prozessoren können das Gleiche tun. In den "alten Tagen" gab es 8-Bit-Prozessoren, die Gleitkomma-Mathematik beherrschten. Aber sie waren slooooooow.
"32-Bit" ist wirklich eine Methode zur Kategorisierung von Prozessoren, keine feste Regel. Ein "32-Bit" -Prozessor verfügt normalerweise über 32-Bit-Universalregister, mit denen gearbeitet werden kann.
Es gibt jedoch keine Anforderung, dass alles im Prozessor in 32-Bit ausgeführt werden muss. Beispielsweise war es für einen "32-Bit" -Computer nicht ungewöhnlich, einen 28-Bit-Adressbus zu haben, da die Herstellung der Hardware billiger war. 64-Bit-Computer haben aus dem gleichen Grund oft nur einen 40-Bit- oder 48-Bit-Speicherbus.
Fließkomma-Arithmetik ist ein weiterer Ort, an dem Größen variieren. Viele 32-Bit-Prozessoren unterstützen 64-Bit-Gleitkommazahlen. Dazu wurden die Gleitkommawerte in Sonderregistern gespeichert, die breiter als die Universalregister waren. Um eine dieser großen Gleitkommazahlen in den Sonderregistern zu speichern, würde man zuerst die Zahl auf zwei Universalregister aufteilen und dann einen Befehl ausgeben, um sie in den Sonderregistern zu einem Gleitkomma zu kombinieren. Sobald sie in diesen Gleitkommaregistern sind, werden die Werte als 64-Bit-Gleitkommazahlen und nicht als ein Paar von 32-Bit-Hälften bearbeitet.
Ein Sonderfall ist die von Ihnen erwähnte 80-Bit-Arithmetik. Wenn Sie mit Gleitkommazahlen gearbeitet haben, sind Sie mit der Ungenauigkeit vertraut, die sich aus Gleitkomma-Abrundungsproblemen ergibt. Eine Lösung für die Abrundung besteht darin, mehr Präzision zu haben, aber dann müssen Sie größere Zahlen speichern und die Entwickler zwingen, ungewöhnlich große Gleitkommawerte im Speicher zu verwenden.
Die Intel-Lösung besteht darin, dass die Gleitkommaregister alle aus 80 Bit bestehen. Die Anweisungen zum Verschieben von Werten zu / von diesen Registern funktionieren jedoch primär mit 64-Bit-Zahlen. Solange Sie vollständig im x87-Gleitkommastapel von Intel arbeiten, werden alle Ihre Vorgänge mit einer Genauigkeit von 80 Bit ausgeführt. Wenn Ihr Code einen dieser Werte aus den Gleitkommaregistern ziehen und irgendwo speichern muss, wird er auf 64-Bit gekürzt.
Moral der Geschichte: Kategorisierungen wie "32-Bit" sind immer dunstiger, wenn Sie tiefer in die Dinge einsteigen!
Bei einer "32-Bit" -CPU handelt es sich bei den meisten Datenregistern um 32-Bit-Register, und die meisten Befehle verarbeiten Daten in diesen 32-Bit-Registern. Eine 32-Bit-CPU überträgt wahrscheinlich auch jeweils 32-Bit-Daten zum und vom Speicher. Die meisten Register, die 32-Bit sind, bedeuten nicht, dass alle Register 32-Bit sind. Die kurze Antwort lautet, dass eine 32-Bit-CPU einige Funktionen haben kann, die andere Bitanzahl verwenden, wie z. B. 80-Bit-Gleitkommaregister und entsprechende Anweisungen.
Wie @spudone in einem Kommentar zur Antwort von @ ultrasawblade sagte, war die erste x86-CPU mit integrierten Gleitkommaoperationen der Intel i486 (speziell der 80486DX, aber nicht der 80486SX), der laut Seite 15-1 der i486-Mikroprozessor-Programmierer Referenzhandbuch , enthält in seinen numerischen Registern "Acht einzeln adressierbare numerische 80-Bit-Register". Der i486 verfügt über einen 32-Bit-Speicherbus, sodass für die Übertragung eines 80-Bit-Werts drei Speicheroperationen erforderlich sind.
Der Vorgänger der 486-Generation, der i386, hatte keine integrierten Gleitkommaoperationen. Stattdessen wurde die Verwendung eines externen Gleitkomma-Coprozessors (80387) unterstützt. Dieser Coprozessor verfügte über nahezu dieselbe Funktionalität wie der i486, wie Sie auf Seite 2-1 des Referenzhandbuchs des 80387-Programmierers sehen können .
Das 80-Bit-Gleitkommaformat scheint mit dem 8087, dem mathematischen Coprozessor für 8086 und 8088, entstanden zu sein. Die 8086 und 8088 waren 16-Bit-CPUs (mit 16-Bit- und 8-Bit-Speicherbussen) und waren noch in der Lage Verwenden des 80-Bit-Gleitkommaformats unter Ausnutzung der 80-Bit-Register im Coprozessor.