Wie kann ein 80-Bit-Gleitkomma von einem 32-Bit-System verwendet werden? [Duplikat]

13

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 ...

markzzz
quelle
8
Auf die gleiche Weise wird eine 64-Bit-Gleitkommazahl erstellt. Es werden 3 oder (2) 32-Bit-Register verwendet. Da eine 80-Bit-Gleitkommazahl nicht einmal eine Standardgröße ist, wäre sie tatsächlich eine 96-Bit-Zahl, wobei nur 80-Bit verwendet werden.
Ramhound
5
Wenn Sie sich Sorgen über Plattformprobleme machen, sind Sie besorgt über das Innenleben der CPU, wie andere bereits gesagt haben, und darüber, wie Anweisungen nativ auf dem System ausgeführt werden. IEEE754-Nummern können normalerweise direkt in den Ausführungseinheiten der FPUs Ihrer CPU verarbeitet werden, wohingegen für eine 128-Bit-Nummer die Verwendung mehrerer Befehle erforderlich ist, die so programmiert sind, dass sie die Bedeutung des von der Anwendung bewerteten Werts aggregieren können. Das überlässt die Verarbeitung der Nummer dem Antrag.
Frank Thomas
2
@ Ƭᴇcʜιᴇ007 Nicht ganz ein Narr , dass ein. In diesem Fall geht es mehr um den Unterschied zwischen einer Zahl und ihrer Text- / ASCII-Darstellung, obwohl einige dieser Antworten dies möglicherweise auch ansprechen.
Bob
3
In praktisch allen modernen Maschinen wird Floating Point von einem separaten Prozessor verarbeitet (in der Regel jedoch auf demselben Chip wie der Hauptprozessor). Alle diese Prozessoren wissen, wie man mit 80-Bit umgeht (obwohl es einige viel schneller machen als andere). ( Und die "Breite" eines Prozessors ist sowieso eine Fiktion. )
Daniel R Hicks
6
@Ramhound: Nein, 80 Bits sind eine 8087-Besonderheit und es wird 1 FP-Register verwendet. Es ist definitiv keine 96-Bit-Zahl.
MSalters

Antworten:

35

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.

LawrenceC
quelle
4
Alles, was Sie aus meiner Inspiration hinzugefügt haben, ist korrekt, also keine Sorge :) Nur ein Punkt, den ich erwähnen sollte: Obwohl Sie native CPU-Anweisungen verwenden können, bei denen eine Gleitkommaeinheit vorhanden ist, können Sie auch Gleitkommaoperationen in Software ausführen (mit äquivalenten bitweisen Schritten) oder ganzzahlige mathematische Operationen). Um dies zu erreichen, können Sie bei genügendem Speicherplatz auch Zahlen mit willkürlicher Genauigkeit (im Gegensatz zu unseren festen 64-Bit- oder 80-Bit- Zahlen in diesem Fall) mithilfe von Softwarealgorithmen / -bibliotheken verwenden (eine häufig verwendete ist GNU Multiple Precision) Bibliothek ).
Durchbruch
1
Nitpick: erste Intel integrierte FPU war im 80486DX, nicht im 80386.
spudone 30.07.14
2
@markzzz: Nichts ist verrückt, wenn es benötigt wird. Es ist verrückt, 16-Bit-Schwimmer zur Simulation einer Atombombe zu verwenden, um Ihren Nuklearvorrat zu bewerten, da dies nicht präzise genug ist, um auf das Ergebnis zu vertrauen. In diesem Fall sind 32 Bit erforderlich (und ja, früher wurden diese Berechnungen auf 16-Bit-PDPs durchgeführt). In ähnlicher Weise ist die Verwendung von 32-Bit-Folaten zur Simulation des Klimas aufgrund der chaotischen Natur der Berechnungen nicht präzise genug.
Slebetman
2
FWIW, die gebräuchliche Methode, Gleitkommaoperationen auf Maschinen ohne FP-Einheiten der gewünschten Größe zu implementieren, ist die Verwendung von Ganzzahlanweisungen in der Software. Denn am Ende des Tages sind Exponent und Mantisse der Gleitkommazahl nur ganze Zahlen. Auf diese Weise interpretieren wir sie und geben ihnen ihre besonderen Bedeutungen.
Slebetman
2
@PTwr auf x86 haben Sie tatsächlich 7 verwendbare GPRs für Daten, einschließlich EBP. Es ist nur so, dass ABI der meisten Sprachimplementierungen dieses Register für Stapelrahmenzeiger reserviert. Aber zB mit GCC können Sie -fomit-frame-pointerdieses Register zurückbekommen.
Ruslan
13

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. ADCauf 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.

Durchbruch
quelle
2
Sie versäumen es, das wichtigste Detail zu erwähnen: Die x87-FPU auf der x86-Plattform verfügt über 80-Bit-Gleitkommaregister. Die nativen Berechnungen werden also auf 80-Bit-Gleitkommazahlen durchgeführt, ohne dass Software emuliert werden muss.
Matteo Italia
@ MatteoItalia Ich sehe das jetzt, danke. Ich dachte, die ursprüngliche Frage sollte einen allgemeineren Überblick darüber geben, wie man Operationen mit Zahlen ausführen kann, die größer als das Prozessorwort sind, und nicht die spezifische Implementierung von erweiterten 80-Bit-Floats in x86 (auch, warum mein Beispiel 90 Bit anstelle von x86 ist) 80 ...). Ich habe die Antwort jetzt aktualisiert, um dies besser widerzuspiegeln. Danke für die Hinweise.
Durchbruch
5

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.

Floris
quelle
1
Sie waren erst nach einem bestimmten Punkt langsam. Sie könnten "schnelle" Gleitkommaoperationen schreiben, wenn Sie sich auf eine bestimmte Spezifikation beschränken.
Ramhound
3

"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!

Cort Ammon - Setzen Sie Monica wieder ein
quelle
Aber wenn ich 32-Bit-Gleitkommawerte in einem 16-Bit-System verwende (oder 64-Bit-Gleitkommawerte in einem 32-Bit-System), benötigt es nur mehr Speicher (da es zweimal registriert werden muss)? Oder ist die Verarbeitung der Informationen mit einem zusätzlichen Aufwand verbunden, sodass mehr Zeit erforderlich ist?
Markzzz
@markzzz: Das Arbeiten mit mehreren Registern nimmt fast immer mehr Zeit in
Anspruch
Das Laden des 32-Bit-Gleitkommawerts in die Spezialregister dauert länger. Sobald sie jedoch als 32-Bit-Gleitkommawerte in den Spezial-Gleitkommaregistern gespeichert sind, arbeitet die Hardware mit diesen Gleitkommawerten mit voller Geschwindigkeit. Denken Sie daran, "16-Bit" bezieht sich nur auf die Größe der ALLGEMEINEN Zweckregister. Die Gleitkommaregister sind speziell für ihre Aufgabe dimensioniert und können breiter sein (in Ihrem Fall 32 Bit breit)
Cort Ammon - Reinstate Monica
2

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.

ShadSterling
quelle