Comment une virgule flottante 80 bits peut-elle être utilisée par un système 32 bits? [dupliquer]

13

Puisqu'un système 32 bits ne peut pas gérer un nombre 2 ^ 33 (car la limite évidente de 32 bits), comment gérer un nombre à virgule flottante 80 bits ?

Il devrait nécessiter "80 bits" ...

markzzz
la source
8
De la même façon, il fait un nombre à virgule flottante 64 bits. Il utilise 3 ou (2) registres 32 bits. Étant donné que le nombre à virgule flottante de 80 bits n'est même pas une taille standard, ce serait en fait un nombre de 96 bits avec seulement 80 bits utilisés.
Ramhound
5
lorsque vous vous inquiétez de la morsure de la plate-forme, vous vous inquiétez du fonctionnement interne du processeur, comme d'autres l'ont dit, et de la façon dont les instructions sont exécutées en mode natif sur le système. Les nombres IEEE754 sont généralement directement traitables dans les unités d'exécution FPU de votre CPU, alors qu'un nombre 128 bits nécessiterait l'utilisation de plusieurs instructions programmées de manière à pouvoir agréger la signification de la valeur que l'application évalue. ce qui laisse le traitement du numéro à la demande.
Frank Thomas
2
@ Ƭᴇcʜιᴇ007 Pas tout à fait dupe de celui- là. Celui-ci concerne davantage la différence entre un nombre et sa représentation texte / ASCII, bien que certaines de ces réponses puissent également résoudre ce problème.
Bob
3
Dans pratiquement toutes les machines modernes, la virgule flottante est gérée par un processeur séparé (bien que généralement sur la même puce que le processeur principal). Tous ces processeurs savent comment gérer le 80 bits (bien que certains le fassent beaucoup plus rapidement que d'autres). ( Et la "largeur" ​​d'un processeur est en quelque sorte une fiction. )
Daniel R Hicks
6
@Ramhound: Non, 80 bits est une particularité 8087, et il utilise 1 registre FP. Ce n'est certainement pas un nombre de 96 bits.
MSalters

Réponses:

35

L'une des significations d'un processeur 32 bits est que ses registres ont une largeur de 32 bits. Cela ne signifie pas qu'il ne peut pas traiter, par exemple, les nombres 64 bits, mais simplement qu'il doit d'abord traiter la moitié inférieure 32 bits, puis la moitié supérieure 32 bits. (C'est pourquoi les processeurs ont un indicateur de report .) C'est plus lent que si le processeur pouvait simplement charger les valeurs dans un registre 64 bits plus large, mais toujours possible.

Ainsi, le «témoin» d'un système ne limite pas nécessairement la taille des nombres qu'un programme peut traiter, car vous pouvez toujours décomposer des opérations qui ne rentrent pas dans les registres du processeur en plusieurs opérations. Cela rend donc les opérations plus lentes, consomme plus de mémoire (si vous devez utiliser la mémoire comme un "bloc-notes") et plus difficile à programmer, mais les opérations sont toujours possibles.

Cependant, rien de tout cela n'a d'importance avec, par exemple, les processeurs Intel 32 bits et virgule flottante, car la partie à virgule flottante du CPU a ses propres registres et ils ont une largeur de 80 bits. (Au début de l'histoire du x86, la capacité à virgule flottante était une puce distincte, elle a été intégrée dans le processeur à partir de 80486DX.)


La réponse de @ Breakthrough m'a inspiré à ajouter ceci.

Les valeurs à virgule flottante, dans la mesure où elles sont stockées dans les registres FPU, fonctionnent très différemment des valeurs entières binaires.

Les 80 bits d'une valeur en virgule flottante sont divisés entre une mantisse et un exposant (il y a aussi la "base" en nombres à virgule flottante qui est toujours 2). La mantisse contient les chiffres significatifs et l'exposant détermine la taille de ces chiffres significatifs. Il n'y a donc pas de "débordement" dans un autre registre, si votre nombre devient trop grand pour tenir dans la mantisse, votre exposant augmente et vous perdez en précision - c'est-à-dire que lorsque vous le convertissez en entier, vous perdrez des décimales à droite - c'est pourquoi on l'appelle virgule flottante.

Si votre exposant est trop grand, vous avez alors un débordement en virgule flottante, mais vous ne pouvez pas facilement l'étendre à un autre registre car l'exposant et la mantisse sont liés ensemble.

Je pourrais être inexact et erroné à ce sujet, mais je crois que c'est l'essentiel. (Cet article Wikipedia illustre un peu plus succinctement ce qui précède.)

C'est OK que cela fonctionne totalement différemment puisque toute la partie "virgule flottante" du CPU est en quelque sorte dans son propre monde - vous utilisez des instructions CPU spéciales pour y accéder et ainsi de suite. En outre, vers le point de la question, car il est séparé, le témoin du FPU n'est pas étroitement couplé au témoin du processeur natif.

LawrenceC
la source
4
Tout ce que vous avez ajouté de mon inspiration est correct, donc ne vous inquiétez pas :) Un seul point que je dois mentionner, bien que vous puissiez utiliser des instructions CPU natives là où une unité à virgule flottante existe, on peut également effectuer des opérations à virgule flottante dans le logiciel (avec un bit équivalent équivalent ou opérations mathématiques entières). Pour étendre ce point, avec suffisamment de mémoire, vous pouvez également avoir des nombres de précision arbitraires (par opposition à nos 64 bits fixes ou 80 bits dans ce cas) en utilisant des algorithmes / bibliothèques logiciels (l'un couramment utilisé est le GNU Multiple Precision bibliothèque ).
Percée du
1
Nitpick: le premier FPU intégré Intel était dans le 80486DX, pas le 80386.
Spudone
2
@markzzz: Rien n'est fou s'il est requis. Utiliser des flotteurs 16 bits pour simuler une bombe atomique afin d'évaluer votre stock nucléaire est fou car il n'est pas assez précis pour que vous ayez confiance dans le résultat. Dans ce cas, 32 bits sont nécessaires (et oui, autrefois, ces calculs étaient effectués sur des PDP 16 bits). De même, l'utilisation de folats 32 bits pour simuler le climat n'est pas suffisamment précise en raison de la nature chaotique des calculs.
slebetman
2
FWIW, la façon courante d'implémenter des opérations à virgule flottante sur des machines sans unités FP de la taille souhaitée est de le faire dans un logiciel en utilisant des instructions entières. Parce qu'à la fin de la journée, l'exposant et la mantisse du nombre à virgule flottante ne sont que des entiers. C'est la façon dont nous les interprétons qui leur donne leur signification particulière.
slebetman
2
@PTwr sur x86, vous disposez en fait de 7 GPR utilisables pour les données, EBP inclus. C'est juste que l'ABI de la plupart des implémentations de langues réserve ce registre pour le pointeur de trame de pile. Mais par exemple avec GCC, vous pouvez utiliser -fomit-frame-pointerpour récupérer ce registre.
Ruslan
13

32 bits, 64 bits et 128 bits font tous référence à la longueur de mot du processeur, qui peut être considérée comme le "type de données fondamental". Souvent, c'est le nombre de bits transférés vers / depuis la RAM du système et la largeur des pointeurs (bien que rien ne vous empêche d'utiliser un logiciel pour accéder à plus de RAM que ce à quoi un seul pointeur peut accéder).

En supposant une vitesse d'horloge constante (ainsi que tout le reste de l'architecture étant constant) et en supposant que les lectures / écritures en mémoire sont à la même vitesse (nous supposons 1 cycle d'horloge ici, mais c'est loin d'être le cas dans la vie réelle), vous pouvez ajouter deux nombres 64 bits en un seul cycle d'horloge sur une machine 64 bits (trois si vous comptez récupérer les nombres dans la RAM):

ADDA [NUM1], [NUM2]
STAA [RESULT]

Nous pouvons également faire le même calcul sur une machine 32 bits ... Cependant, sur une machine 32 bits, nous devons le faire dans le logiciel, car les 32 bits inférieurs doivent être ajoutés en premier, compenser le débordement, puis ajouter les 64 bits supérieurs:

     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]

En parcourant ma syntaxe d'assemblage composée, vous pouvez facilement voir comment des opérations de plus grande précision peuvent prendre un temps exponentiellement plus long sur une machine de longueur de mot inférieure. C'est la vraie clé des processeurs 64 bits et 128 bits: ils nous permettent de gérer un plus grand nombre de bits en une seule opération. Certaines machines incluent des instructions pour ajouter d'autres quantités avec un report (par exemple ADCsur x86), mais l'exemple ci-dessus a en tête des valeurs de précision arbitraires.


Maintenant, pour étendre cela à la question, il est simple de voir comment nous pourrions ajouter des nombres plus grands que les registres dont nous disposons - nous divisons simplement le problème en morceaux de la taille des registres et travaillons à partir de là. Bien que comme mentionné par @MatteoItalia , la pile FPU x87 prend en charge nativement des quantités de 80 bits, dans les systèmes ne prenant pas en charge cette fonction (ou dans les processeurs dépourvus d'une unité à virgule flottante!), Les calculs / opérations équivalents doivent être effectués dans le logiciel .

Donc, pour un nombre de 80 bits, après avoir ajouté chaque segment de 32 bits, on vérifierait également le débordement dans le bit de 81 bits, et éventuellement mettre à zéro les bits d'ordre supérieur. Ces vérifications / zéros sont effectués automatiquement pour certaines instructions x86 et x86-64, où les tailles d'opérande source et de destination sont spécifiées (bien qu'elles ne soient spécifiées qu'en puissances de 2 à partir de 1 octet de large).

Bien sûr, avec les nombres à virgule flottante, on ne peut pas simplement effectuer l'addition binaire car la mantisse et les chiffres significatifs sont regroupés sous forme de décalage. Dans l'ALU sur un processeur x86, il existe un circuit matériel pour effectuer cela pour les flottants IEEE 32 bits et 64 bits; cependant , même en l'absence d'une unité à virgule flottante (FPU), les mêmes calculs peuvent être effectués dans un logiciel (par exemple, en utilisant la bibliothèque scientifique GNU , qui utilise un FPU lorsqu'il est compilé sur des architectures avec, retombant dans des algorithmes logiciels si aucun matériel à virgule flottante n'est disponible [par exemple pour les microcontrôleurs intégrés dépourvus de FPU]).

Avec suffisamment de mémoire, on peut également effectuer des calculs sur des nombres de précision arbitraire (ou "infinie" - dans des limites réalistes), en utilisant plus de mémoire car plus de précision est requise. Une implémentation de cela existe dans la bibliothèque GNU Multiple Precision , permettant une précision illimitée (jusqu'à ce que votre RAM soit pleine, bien sûr) sur les opérations entières, rationnelles et à virgule flottante.

Percée
la source
2
Vous omettez de mentionner le détail le plus important: le FPU x87 sur la plate-forme x86 possède des registres à virgule flottante de 80 bits, de sorte que ses calculs natifs sont en fait effectués sur des flottants de 80 bits, pas besoin d'émuler quoi que ce soit dans le logiciel.
Matteo Italia
@MatteoItalia Je le vois maintenant, merci. Je pensais que la question d'origine demandait un aperçu plus générique de la façon dont on pouvait effectuer des opérations sur des nombres supérieurs à la taille du mot du processeur, et non l'implémentation spécifique de flottants 80 bits étendus en x86 (aussi pourquoi mon exemple était de 90 bits au lieu de 80 ...). J'ai mis à jour la réponse maintenant pour mieux refléter cela, merci pour l'avertissement.
Percée
5

L'architecture de la mémoire du système peut seulement vous permettre de déplacer 32 bits à la fois - mais cela ne l'empêche pas d'utiliser des nombres plus importants.

Pensez à la multiplication. Vous connaissez peut-être vos tables de multiplication jusqu'à 10x10, mais vous n'avez probablement aucun problème à effectuer 123x321 sur un morceau de papier: vous le divisez simplement en de nombreux petits problèmes, en multipliant les chiffres individuels, en prenant soin du transport, etc.

Les processeurs peuvent faire la même chose. Dans les temps anciens, vous disposiez de processeurs 8 bits capables de faire des calculs en virgule flottante. Mais ils étaient slooooooow.

Floris
la source
1
Ils n'étaient lents qu'après un certain point. Vous pouvez écrire des opérations à virgule flottante "rapides" si vous vous limitez à une certaine spécification.
Ramhound
3

"32 bits" est vraiment un moyen de catégoriser les processeurs, pas une décision figée. un processeur "32 bits" a généralement des registres à usage général 32 bits avec lesquels travailler.

Cependant, il n'y a aucune exigence définie dans la pierre que tout dans le processeur soit fait en 32 bits. Par exemple, il n'était pas rare qu'un ordinateur "32 bits" ait un bus d'adresse 28 bits, car il était moins coûteux de fabriquer le matériel. Les ordinateurs 64 bits n'ont souvent qu'un bus mémoire 40 bits ou 48 bits pour la même raison.

L'arithmétique en virgule flottante est un autre endroit où les tailles varient. De nombreux processeurs 32 bits prennent en charge les nombres à virgule flottante 64 bits. Ils l'ont fait en stockant les valeurs à virgule flottante dans des registres spéciaux qui étaient plus larges que les registres à usage général. Pour stocker l'un de ces grands nombres à virgule flottante dans les registres spéciaux, on diviserait d'abord le nombre sur deux registres à usage général, puis émettrait une instruction pour les combiner en un flottant dans les registres spéciaux. Une fois dans ces registres à virgule flottante, les valeurs seraient manipulées comme des flottants 64 bits, plutôt que comme une paire de moitiés 32 bits.

L'arithmétique 80 bits que vous mentionnez en est un cas particulier. Si vous avez travaillé avec des nombres à virgule flottante, vous connaissez l’imprécision qui découle des problèmes d’arrondi en virgule flottante. Une solution pour l'arrondi consiste à avoir plus de bits de précision, mais vous devez ensuite stocker de plus grands nombres et forcer les développeurs à utiliser des valeurs à virgule flottante inhabituellement grandes en mémoire.

La solution Intel est que les registres à virgule flottante sont tous de 80 bits, mais les instructions pour déplacer des valeurs vers / depuis ces registres fonctionnent principalement avec des nombres de 64 bits. Tant que vous opérez entièrement dans la pile à virgule flottante x87 d'Intel, toutes vos opérations sont effectuées avec 80 bits de précision. Si votre code doit extraire une de ces valeurs des registres à virgule flottante et la stocker quelque part, il la tronque à 64 bits.

Morale de l'histoire: les catégorisations comme "32 bits" sont toujours plus floues quand on approfondit les choses!

Cort Ammon
la source
Mais si j'utilise des valeurs à virgule flottante 32 bits dans un système 16 bits (ou des valeurs à virgule flottante 64 bits dans un système 32 bits), cela ne nécessite que plus de mémoire (car il doit enregistrer deux fois)? Ou le traitement des informations ajoutera des frais généraux, alors cela prendra plus de temps?
markzzz
@markzzz: Travailler avec plusieurs registres prend presque toujours plus de temps
Mooing Duck
Le chargement de la valeur à virgule flottante 32 bits dans les registres à usage spécial prendra plus de temps. Cependant, une fois qu'ils sont stockés sous forme de flottants 32 bits dans les registres à virgule flottante à usage spécial, le matériel fonctionnera à pleine vitesse sur ces valeurs à virgule flottante. N'oubliez pas que «16 bits» fait uniquement référence à la taille des registres à usage général. Les registres à virgule flottante sont spécialement dimensionnés pour leur tâche et peuvent être plus larges (32 bits de large dans votre cas)
Cort Ammon
2

Un processeur "32 bits" est un processeur où la plupart des registres de données sont des registres 32 bits, et la plupart des instructions opèrent sur les données de ces registres 32 bits. Un processeur 32 bits est également susceptible de transférer des données vers et depuis la mémoire 32 bits à la fois. La plupart des registres étant 32 bits ne signifie pas que tous les registres sont 32 bits. La réponse courte est qu'un processeur 32 bits peut avoir certaines fonctionnalités qui utilisent d'autres nombres de bits, tels que des registres à virgule flottante 80 bits et des instructions correspondantes.

Comme @spudone l'a dit dans un commentaire sur la réponse de @ ultrasawblade, le premier processeur x86 à avoir intégré des opérations à virgule flottante était l'Intel i486 (en particulier le 80486DX mais pas le 80486SX), qui, selon la page 15-1 des programmeurs de microprocesseur i486 Le manuel de référence inclut dans ses registres numériques "huit registres numériques de 80 bits adressables individuellement". L'i486 possède un bus mémoire 32 bits, donc le transfert d'une valeur 80 bits nécessiterait 3 opérations de mémoire.

Le prédécesseur de la génération 486, le i386, n'avait pas d'opérations intégrées en virgule flottante. Au lieu de cela, il a pris en charge l'utilisation d'un "coprocesseur" à virgule flottante externe, le 80387. Ce coprocesseur avait presque les mêmes fonctionnalités que celles intégrées au i486, comme vous pouvez le voir à la page 2-1 du manuel de référence du programmeur 80387 .

Le format à virgule flottante 80 bits semble provenir du 8087, le coprocesseur mathématique pour les 8086 et 8088. Les 8086 et 8088 étaient des processeurs 16 bits (avec des bus mémoire 16 bits et 8 bits), et étaient toujours capables d'utiliser le format à virgule flottante 80 bits, en tirant parti des registres 80 bits du coprocesseur.

ShadSterling
la source