¿Cómo puede un punto flotante de 80 bits ser utilizado por un sistema de 32 bits? [duplicar]

13

Dado que un sistema de 32 bits no puede administrar un número 2 ^ 33 (debido al límite obvio de 32 bits), ¿cómo puede administrar un número de coma flotante de 80 bits ?

Debería requerir "80 bits" ...

markzzz
fuente
8
Del mismo modo que hace un número de coma flotante de 64 bits. Utiliza 3 o (2) registros de 32 bits. Dado que el número de coma flotante de 80 bits ni siquiera es un tamaño estándar, en realidad sería un número de 96 bits con solo 80 bits en uso.
Ramhound
55
cuando le preocupa la mordedura de la plataforma, le preocupa el funcionamiento interno de la CPU, como han dicho otros, y la forma en que las instrucciones se ejecutan de forma nativa en el sistema. Los números IEEE754 generalmente se pueden procesar directamente en las unidades de ejecución de FPU de su CPU, mientras que un número de 128 bits requeriría el uso de múltiples instrucciones programadas de modo que puedan agregar el significado del valor que la aplicación está evaluando. eso deja el procesamiento del número a la aplicación.
Frank Thomas
2
@ Ƭᴇcʜιᴇ007 No soy un tonto de eso . Esa es más sobre la diferencia entre un número y su representación de texto / ASCII, aunque algunas de esas respuestas también pueden abordar esto.
Bob
3
En prácticamente todas las máquinas modernas, la coma flotante es manejada por un procesador separado (aunque generalmente en el mismo chip que el procesador principal). Todos estos procesadores saben cómo manejar 80 bits (aunque algunos lo hacen mucho más rápido que otros). ( Y el "ancho" de un procesador es una especie de ficción de todos modos. )
Daniel R Hicks
66
@Ramhound: No, 80 bits es una peculiaridad 8087, y utiliza 1 registro FP. Definitivamente no es un número de 96 bits.
MSalters

Respuestas:

35

Uno de los significados de una CPU de 32 bits es que sus registros tienen 32 bits de ancho. Esto no significa que no pueda lidiar con, digamos, números de 64 bits, solo que tiene que lidiar primero con la mitad inferior de 32 bits, luego con la mitad superior de 32 bits. (Es por eso que las CPU tienen un indicador de acarreo ). Es más lento que si la CPU pudiera cargar los valores en un registro más amplio de 64 bits, pero aún es posible.

Por lo tanto, el "bitness" de un sistema no limita necesariamente el tamaño de los números con los que puede lidiar un programa, porque siempre puede dividir las operaciones que no encajan en los registros de la CPU en múltiples operaciones. Por lo tanto, hace que las operaciones sean más lentas, consuma más memoria (si tiene que usar la memoria como "bloc de notas") y más difícil de programar, pero las operaciones aún son posibles.

Sin embargo, nada de eso importa, por ejemplo, con procesadores Intel de 32 bits y coma flotante, ya que la parte de coma flotante de la CPU tiene sus propios registros y tienen 80 bits de ancho. (Al principio de la historia del x86, la capacidad de punto flotante era un chip separado, estaba integrado en la CPU a partir de 80486DX).


La respuesta de @ Breakthrough me inspiró a agregar esto.

Los valores de coma flotante, en la medida en que están almacenados en los registros de FPU, funcionan de manera muy diferente a los valores enteros binarios.

Los 80 bits de un valor de coma flotante se dividen entre una mantisa y un exponente (también existe la "base" en los números de coma flotante que siempre es 2). La mantisa contiene los dígitos significativos, y el exponente determina qué tan grandes son esos dígitos significativos. Por lo tanto, no hay "desbordamiento" en otro registro, si su número es demasiado grande para caber en la mantisa, su exponente aumenta y pierde precisión, es decir, cuando lo convierte en un número entero, perderá decimales a la derecha. Por eso se llama coma flotante.

Si su exponente es demasiado grande, entonces tiene un desbordamiento de punto flotante, pero no puede extenderlo fácilmente a otro registro ya que el exponente y la mantisa están unidos.

Podría ser inexacto e incorrecto sobre algo de eso, pero creo que esa es la esencia. (Este artículo de Wikipedia ilustra un poco más brevemente lo anterior).

Está bien que esto funcione de manera totalmente diferente ya que toda la parte de "punto flotante" de la CPU está en su propio mundo: se usan instrucciones especiales de la CPU para acceder a ella y demás. Además, hacia el punto de la pregunta, debido a que es independiente, el bitness de la FPU no está estrechamente acoplado con el bitness de la CPU nativa.

LawrenceC
fuente
44
Todo lo que agregó de mi inspiración es correcto, así que no se preocupe allí :) Solo debo mencionar un punto, aunque puede usar instrucciones de CPU nativas donde exista una unidad de punto flotante, también puede realizar operaciones de punto flotante en software (con bit a bit equivalente o operaciones matemáticas enteras). Para extenderse a ese punto, con suficiente memoria, también puede tener números de precisión arbitrarios (a diferencia de nuestros 64 bits fijos u 80 bits en este caso) utilizando algoritmos / bibliotecas de software (uno comúnmente usado es la precisión múltiple GNU biblioteca ).
Avance el
1
Nitpick: la primera FPU integrada de Intel fue en el 80486DX, no en el 80386.
spudone
2
@markzzz: Nada es una locura si es necesario. El uso de flotadores de 16 bits para simular una bomba atómica con el fin de evaluar su reserva nuclear es una locura porque no es lo suficientemente preciso para que tenga confianza en el resultado. En cuyo caso se requieren 32 bits (y sí, en los viejos tiempos estos cálculos se realizaban en PDP de 16 bits). Del mismo modo, el uso de folats de 32 bits para simular el clima no es lo suficientemente preciso debido a la naturaleza caótica de los cálculos.
slebetman
2
FWIW, la forma común de implementar operaciones de punto flotante en máquinas sin unidades FP del tamaño que desea es hacerlo en software utilizando instrucciones enteras. Porque, al final del día, tanto el exponente como la mantisa del número de coma flotante son simplemente enteros. Es cómo los interpretamos que les da sus significados especiales.
slebetman
2
@PTwr en x86 en realidad tiene 7 GPR utilizables para datos, incluido EBP. Es solo que ABI de la mayoría de las implementaciones de idiomas reserva este registro para el puntero de marco de pila. Pero, por ejemplo, con GCC puede usar -fomit-frame-pointerpara recuperar ese registro.
Ruslan
13

32 bits, 64 bits y 128 bits se refieren a la longitud de palabra del procesador, que puede considerarse como el "tipo de datos fundamental". A menudo, este es el número de bits transferidos a / desde la RAM del sistema, y ​​el ancho de los punteros (aunque nada le impide usar software para acceder a más RAM de lo que puede acceder un puntero).

Suponiendo una velocidad de reloj constante (así como que todo lo demás en la arquitectura sea constante), y suponiendo que las lecturas / escrituras de memoria sean de la misma velocidad (asumimos 1 ciclo de reloj aquí, pero esto está lejos del caso en la vida real), puede agregue dos números de 64 bits en un solo ciclo de reloj en una máquina de 64 bits (tres si cuenta recuperar los números de la RAM):

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

También podemos hacer el mismo cálculo en una máquina de 32 bits ... Sin embargo, en una máquina de 32 bits, necesitamos hacer esto en el software, ya que primero se deben agregar los 32 bits inferiores, compensar el desbordamiento y luego agregar los 64 bits superiores:

     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]

Al revisar mi sintaxis de ensamblaje inventada, puede ver fácilmente cómo las operaciones de mayor precisión pueden llevar un tiempo exponencialmente más largo en una máquina de menor longitud de palabra. Esta es la clave real de los procesadores de 64 bits y 128 bits: nos permiten manejar grandes cantidades de bits en una sola operación. Algunas máquinas incluyen instrucciones para agregar otras cantidades con un acarreo (por ejemplo, ADCen x86), pero el ejemplo anterior tiene en mente valores de precisión arbitrarios.


Ahora, para extender esto a la pregunta, es simple ver cómo podríamos agregar números más grandes que los registros que tenemos disponibles: simplemente dividimos el problema en trozos del tamaño de los registros y trabajamos desde allí. Aunque, como mencionó @MatteoItalia , la pila x87 FPU tiene soporte nativo para cantidades de 80 bits, en sistemas que carecen de este soporte (¡o procesadores que carecen de una unidad de punto flotante por completo!), Los cálculos / operaciones equivalentes deben realizarse en software .

Entonces, para un número de 80 bits, después de agregar cada segmento de 32 bits, también se verificaría el desbordamiento en el bit de 81 puntos y, opcionalmente, cero los bits de orden superior. Estas verificaciones / ceros se realizan automáticamente para ciertas instrucciones x86 y x86-64, donde se especifican los tamaños de operando de origen y destino (aunque estos solo se especifican en potencias de 2 a partir de 1 byte de ancho).

Por supuesto, con los números de coma flotante, uno no puede simplemente realizar la suma binaria ya que la mantisa y los dígitos significativos se empaquetan en forma de desplazamiento. En la ALU en un procesador x86, hay un circuito de hardware para realizar esto para flotadores IEEE de 32 bits y 64 bits; sin embargo , incluso en ausencia de una unidad de punto flotante (FPU), se pueden realizar los mismos cálculos en el software (por ejemplo, mediante el uso de la Biblioteca Científica GNU , que utiliza una FPU cuando se compila en arquitecturas, recurriendo a algoritmos de software si no hay hardware de punto flotante disponible [por ejemplo, para microcontroladores integrados que carecen de FPU]).

Dada suficiente memoria, también se pueden realizar cálculos sobre números de precisión arbitraria (o "infinita" - dentro de límites realistas), utilizando más memoria ya que se requiere más precisión. Existe una implementación de esto en la biblioteca GNU Multiple Precision , que permite una precisión ilimitada (hasta que su RAM esté llena, por supuesto) en operaciones de punto entero, racional y de punto flotante.

Penetración
fuente
2
No menciona el detalle más importante: la FPU x87 en la plataforma x86 tiene registros de coma flotante de 80 bits de ancho, por lo que sus cálculos nativos se realizan en flotadores de 80 bits, sin necesidad de emular nada en el software.
Matteo Italia
@ MatteoItalia Ahora veo eso, gracias. Pensé que la pregunta original era pedir una descripción más genérica de cómo se podían realizar operaciones en números mayores que el tamaño de palabra del procesador, y no la implementación específica de flotantes extendidos de 80 bits en x86 (también por qué mi ejemplo fue de 90 bits en lugar de 80 ...). He actualizado la respuesta ahora para reflejar mejor esto, gracias por el aviso.
Avance el
5

La arquitectura de memoria del sistema solo le permite mover 32 bits a la vez, pero eso no impide que use números más grandes.

Piensa en la multiplicación. Es posible que conozca sus tablas de multiplicar hasta 10x10, pero probablemente no tenga problemas para realizar 123x321 en una hoja de papel: simplemente lo divide en muchos problemas pequeños, multiplica los dígitos individuales y se encarga del transporte, etc.

Los procesadores pueden hacer lo mismo. En los "viejos tiempos" tenías procesadores de 8 bits que podían hacer cálculos de coma flotante. Pero eran muuuuuuuuuuy

Floris
fuente
1
Eran lentos solo después de cierto punto. Podría escribir operaciones de coma flotante "rápidas" si se limita a una determinada especificación.
Ramhound
3

"32 bits" es realmente una forma de categorizar los procesadores, no una decisión establecida. un procesador de "32 bits" generalmente tiene registros de propósito general de 32 bits para trabajar.

Sin embargo, no hay ningún requisito establecido de que todo en el procesador se realice en 32 bits. Por ejemplo, no era desconocido que una computadora de "32 bits" tuviera un bus de direcciones de 28 bits, porque era más barato fabricar el hardware. Las computadoras de 64 bits a menudo solo tienen un bus de memoria de 40 o 48 bits por la misma razón.

La aritmética de coma flotante es otro lugar donde los tamaños varían. Muchos procesadores de 32 bits admiten números de coma flotante de 64 bits. Lo hicieron almacenando los valores de coma flotante en registros especiales que eran más anchos que los registros de propósito general. Para almacenar uno de estos grandes números de coma flotante en los registros especiales, primero se dividiría el número en dos registros de propósito general, luego se emitiría una instrucción para combinarlos en un flotante en los registros especiales. Una vez en esos registros de coma flotante, los valores se manipularían como flotantes de 64 bits, en lugar de como un par de mitades de 32 bits.

La aritmética de 80 bits que menciona es un caso especial de esto. Si ha trabajado con números de coma flotante, está familiarizado con la imprecisión que surge de los problemas de redondeo de coma flotante. Una solución para el redondeo es tener más bits de precisión, pero luego debe almacenar números más grandes y obligar a los desarrolladores a usar valores de punto flotante inusualmente grandes en la memoria.

La solución de Intel es que los registros de coma flotante son todos de 80 bits, pero las instrucciones para mover valores hacia / desde esos registros funcionan principalmente con números de 64 bits. Siempre que opere completamente dentro de la pila de coma flotante x87 de Intel, todas sus operaciones se realizan con 80 bits de precisión. Si su código necesita extraer uno de esos valores de los registros de coma flotante y almacenarlo en algún lugar, lo trunca a 64 bits.

Moraleja de la historia: las categorizaciones como "32 bits" siempre son más peligrosas cuando profundizas en las cosas.

Cort Ammon
fuente
Pero si uso valores de coma flotante de 32 bits en un sistema de 16 bits (o valores de coma flotante de 64 bits en un sistema de 32 bits), ¿solo requiere más memoria (ya que debe registrarse dos veces)? ¿O el procesamiento de la información agregará gastos generales, por lo que tomará más tiempo?
markzzz
@markzzz: Trabajar con múltiples registros casi siempre lleva más tiempo
Mooing Duck
Cargar el valor de coma flotante de 32 bits en los registros de propósito especial llevará más tiempo. Sin embargo, una vez que se almacenan como flotantes de 32 bits en los registros de punto flotante de propósito especial, el hardware funcionará con esos valores de punto flotante a toda velocidad. Recuerde, "16 bits" solo se refiere al tamaño de los registros de propósito GENERAL. Los registros de coma flotante tienen un tamaño especial para su tarea, y pueden ser más anchos (32 bits de ancho en su caso)
Cort Ammon
2

Una CPU de "32 bits" es aquella en la que la mayoría de los registros de datos son registros de 32 bits, y la mayoría de las instrucciones funcionan con datos en esos registros de 32 bits. También es probable que una CPU de 32 bits transfiera datos hacia y desde la memoria de 32 bits a la vez. La mayoría de los registros de 32 bits no significa que todos los registros sean de 32 bits. La respuesta breve es que una CPU de 32 bits puede tener algunas características que usan otros recuentos de bits, como registros de punto flotante de 80 bits y las instrucciones correspondientes.

Como dijo @spudone en un comentario sobre la respuesta de @ ultrasawblade, la primera CPU x86 en tener operaciones de punto flotante integradas fue la Intel i486 (específicamente la 80486DX pero no la 80486SX), que, según la página 15-1 de los programadores de microprocesadores i486 El Manual de referencia incluye en sus registros numéricos "Ocho registros numéricos de 80 bits direccionables individualmente". El i486 tiene un bus de memoria de 32 bits, por lo que transferir un valor de 80 bits requeriría 3 operaciones de memoria.

El predecesor de la generación 486, el i386, no tenía operaciones integradas de punto flotante. En cambio, tenía soporte para usar un "coprocesador" de coma flotante externo, el 80387. Este coprocesador tenía casi la misma funcionalidad que estaba integrada en el i486, como puede ver en la página 2-1 del Manual de referencia del programador 80387 .

El formato de punto flotante de 80 bits parece haberse originado con el 8087, el coprocesador matemático para los 8086 y 8088. Los 8086 y 8088 eran CPU de 16 bits (con buses de memoria de 16 y 8 bits), y aún podían para utilizar el formato de punto flotante de 80 bits, aprovechando los registros de 80 bits en el coprocesador.

ShadSterling
fuente