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" ...
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" ...
Réponses:
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.
-fomit-frame-pointer
pour récupérer ce registre.
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 ADC
sur 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.
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.
"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!
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.