3.6 Multiplicación La multiplicación es una operación mas complicada que la suma y que la resta. Para entender como es que el hardware realiza esta operación, con base en la ALU desarrollada, daremos un repaso de cómo se realiza esta operación de manera manual, recordando así los nombres de los diferentes elementos que intervienen en la operación. Por ejemplo, si multiplicamos 1000 por 1001, tenemos: Multiplicando Multiplicador Producto 1000 x 1001 1000 0000 0000 1000 1001000 El primer operando se llama multiplicando y el segundo multiplicador. Al resultado final se le llama producto. El algoritmo básico estudiado en la primaria, realiza la multiplicación entre el multiplicando y un dígito del multiplicador para obtener un resultado parcial, cada resultado parcial se desplaza un lugar a la derecha. Al final se suman todos los productos parciales desplazados para obtener el producto final. Cuando se trata de números binarios, la obtención de cada producto parcial es inmediata, si el dígito del multiplicador que se está evaluando es 1, el producto parcial es igual al valor del multiplicando; y si es un 0, el resultado parcial es 0. Otra observación importante es que, sin importar la base numérica en la que se obtenga el producto, al multiplicar un número de n-dígitos con otro de m-dígitos, el resultado puede llegar a requerir, a lo mas, de n + m dígitos. En el caso de MIPS se multiplicarán dos registros de 32 bits, de manera que el resultado puede requerir hasta de 64 bits para su representación. Primera versión del Algoritmo y Hardware de la Multiplicación. La primera versión de la implementación se basa en el algoritmo de la primaría, el hardware se muestra en la figura 3.14, el multiplicando debe ubicarse en la mitad izquierda de un registro de 64 bits, para que se vaya desplazando a la izquierda como ocurría con cada producto parcial. El multiplicando se va a sumar con el registro del producto (de 64 bits) y el resultado se va a escribir en este último registro. A diferencia del algoritmo de la primaria, la suma se va a realizar cada vez que el multiplicando se recorra a la izquierda, y no al final de la obtención de todos los productos parciales. El multiplicador estará en un registro de desplazamiento de 32 bits, este registro se desplazará a la derecha de manera que sólo se evalúe al bit menos significativo. El bloque encargado de sincronizar a los demás elementos es el Control, este bloque evalúa al bit menos significativo del multiplicador y en función de ello determina si se sumará al multiplicando con el producto parcial o si solamente se desplazará a la izquierda; también determina cuando la operación debe terminar. La actividad de este bloque se describe en el algoritmo de la figura 3.15, donde se muestra que, debido a que los operandos son de 32 bits, se requiere de 32 iteraciones, y en cada iteración se realizan 3 pasos. Fig. 3.14 Hardware de la multiplicación (primera versión) Fig. 3.15 Algoritmo para la multiplicación (primera versión) Ejemplo: Primer algoritmo de la multiplicación Usando números de 4 bits, para reducir espacio, multiplicar 6diez x 3diez. (0110dos x 0011dos). Respuesta: Debido a que los números son de 4 bits, el algoritmo requerirá de 4 iteraciones, construiremos una tabla mostrando los diferentes pasos en cada iteración: Iteración Paso 0 Valores iniciales 1: 1 => prod = prod + mcando 1 2: Desp. Mcando. a la izq. 3: Desp. Mdor. a la der. 1: 1 => prod = prod + mcando 2 2: Desp. Mcando. a la izq. 3: Desp. Mdor. a la der. 1: 0 => No operación 3 2: Desp. Mcando. a la izq. 3: Desp. Mdor. a la der. 1: 0 => No operación 4 2: Desp. Mcando. a la izq. 3: Desp. Mdor. a la der. Multiplicador 0011 0011 0011 0001 0001 0011 0000 0000 0000 0000 0000 0000 0000 Multiplicando 0000 0110 0000 0110 0000 1100 0000 1100 0000 1100 0001 1000 0001 1000 0001 1000 0011 0000 0011 0000 0011 0000 0110 0000 0110 0000 Producto 0000 0000 0000 0110 0000 0110 0000 0110 0001 0010 0001 0010 0001 0010 0001 0010 0001 0010 0001 0010 0001 0010 0001 0010 0001 0010 En cada iteración se subraya al bit a evaluar (multiplicador[0]). Segunda versión del Algoritmo y Hardware de la Multiplicación. Una observación al hardware de la primera versión es la siguiente: Aunque se suman registros de 64 bits, en realidad la parte significativa de la suma es de 32 bits, ya que en los otros 32 se están sumando 0s. Entonces, es posible reducir la ALU a 32 bits, para ello mantendremos el multiplicando fijo (en un registro de 32 bits) y en lugar de los desplazamientos que éste realizaba a la izquierda, se desplazará a la derecha al producto. El producto se mantiene en un registro de 64 bits, por lo que la suma con el multiplicando, se hará con sus 32 bits mas significativos. La nueva versión para el hardware se muestra en la figura 3.16, mientras que en la figura 3.17 se muestra la nueva versión para el algoritmo. Se conservan las 32 iteraciones y los 3 pasos en cada iteración. Fig. 3.16 Hardware de la multiplicación (segunda versión) Fig. 3.17 Algoritmo para la multiplicación (segunda versión) Ejemplo: Segundo algoritmo de la multiplicación Con este nuevo algoritmo, repetir la multiplicación de 0110dos x 0011dos. Respuesta: Nuevamente construiremos una tabla con los resultados de cada iteración: Iteración Paso 0 Valores iniciales 1: 1 => prod = prod + mcando 1 2: Desp. Producto a la der. 3: Desp. Mdor. a la der. 1: 1 => prod = prod + mcando 2 2: Desp. Producto a la der. 3: Desp. Mdor. a la der. 1: 0 => No operación 3 2: Desp. Producto a la der. 3: Desp. Mdor. a la der. 1: 0 => No operación 4 2: Desp. Producto a la der. 3: Desp. Mdor. a la der. Multiplicador 0011 0011 0011 0001 0001 0011 0000 0000 0000 0000 0000 0000 0000 Multiplicando 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 Producto 0000 0000 0110 0000 0011 0000 0011 0000 1001 0000 0100 1000 0100 1000 0100 1000 0010 0100 0010 0100 0010 0100 0001 0010 0001 0010 La segunda versión requiere de una menor cantidad de Hardware. Aunque se tiene la misma cantidad de pasos, es una versión un poco mas rápida debido a que la suma de datos de 32 bits es más rápida que la suma de datos de 64. Versión final del Algoritmo y Hardware de la Multiplicación. En el hardware mostrado en la figura 3.16 pueden notarse que, el registro del multiplicador y el registro del producto se desplazan a la derecha, y que cuando el algoritmo comienza no importa lo que haya en la mitad derecha del registro del producto, por que se va a perder. Y cuando el algoritmo termina, el registro del multiplicador queda con 0s, es decir, su valor se va perdiendo durante el desarrollo del algoritmo. De manera que puede obtenerse una versión mejorada del hardware, si al comienzo del algoritmo se coloca al multiplicador a la mitad derecha del producto. Con ello, además de reducir los recursos, da pie a un algoritmo mas rápido, por que en lugar de 2 desplazamientos sólo se realizará 1. En la figura 3.18 se muestra la versión final del hardware para la multiplicación y en la figura 3.19 se muestra al algoritmo que desarrollará el control en esta versión final. Puede notarse que en cada iteración se ha reducido a 2 el número de pasos. Fig. 3.18 Hardware de la multiplicación (versión final) Fig. 3.19 Algoritmo para la multiplicación (versión final) Ejemplo: Versión final del algoritmo de la multiplicación Repetir la multiplicación de 0110dos x 0011dos, con el algoritmo de la figura 3.19. Respuesta: En este caso la tabla sólo cuenta con una columna para el multiplicando y otra para el producto: Iteración Paso 0 Valores iniciales 1: 1 => prod = prod + mcando 1 2: Desp. Producto a la der. 1: 1 => prod = prod + mcando 2 2: Desp. Producto a la der. 1: 0 => No operación 3 2: Desp. Producto a la der. 1: 0 => No operación 4 2: Desp. Producto a la der. Multiplicando 0110 0110 0110 0110 0110 0110 0110 0110 0110 Producto 0000 0011 0110 0011 0011 0001 1001 0001 0100 1000 0100 1000 0010 0100 0010 0100 0001 0010 Solo el registro del producto se modifica a lo largo del algoritmo, el multiplicando permanece sin cambios durante todas las iteraciones. En todas las versiones mostradas para la multiplicación, no se hace la distinción entre números con signo o sin signo. Una opción para hacer estas distinciones podría consistir en evaluar los signos de los operandos y con ello determinar el signo del resultado (basándose en las leyes de los signos para la multiplicación). Luego realizar la multiplicación con números positivos y colocar el signo correspondiente al resultado. Este esquema es muy fácil de entender, aunque algo complicado y lento para implementar. El problema es que el hardware y software se fundamentaron en un algoritmo en el que nunca se consideraron los signos de los operandos (por conveniencia, por que es un algoritmo ampliamente conocido). Existen algunos algoritmos que desde un principio consideran los signos de los operandos, uno de ellos es el algoritmo de Booth. 3.7 División La división es la operación complementaria a la multiplicación, nuevamente realizaremos una primera aproximación al hardware y al algoritmo de control, basadas en el algoritmo de la primaria, luego observaremos que mejoras se le pueden hacer, para alcanzar una versión final mas eficiente. Recordemos el algoritmo de la primaria dividiendo 101011 entre 100: Divisor 100 1010 101011 - 100 101 - 100 11 Cociente Dividendo Residuo Estamos considerando la división entera; entonces el resultado va a quedar en dos registros, en uno de ellos se tendrá al cociente y en el otro se tendrá al residuo o resto. Los diferentes componentes de la división están relacionados por: Dividendo = Divisor x Cociente + Residuo Nuevamente, solo consideraremos números positivos para simplificar la estructura y comprensión del algoritmo y hardware de la división. Primera versión del Algoritmo y Hardware de la División. La división se fundamenta en restas, en el algoritmo de la primaria escogemos algunos de los dígitos de la derecha del dividendo “hasta que alcance” el divisor en los bits escogidos. Al hacer la operación de manera manual, es posible determinar por inspección cuantos dígitos son necesarios para que “alcance” el divisor en una parte del dividendo. Pero con hardware, la única manera para determinar si alcanza un número en otro es por medio de una resta. Si después de hacer la resta el resultado es mayor o igual que cero, efectivamente, si alcanzó en divisor en una parte del dividendo. Pero si el resultado es menor que cero, entonces significa que no alcanzó el divisor y habrá que restablecer el valor que el dividendo tenía antes de la resta. El divisor se colocará a la izquierda de un registro de 64 bits y en cada iteración se desplazará a la derecha, para obtener el mismo resultado que el algoritmo de la primaria. El dividendo deberá estar colocado a la derecha de otro registro de 64 bits para que los operandos sean del mismo tamaño y la resta pueda realizarse. Después de todas las restas (32 iteraciones o cuando ya no sea posible restar una vez más al divisor) en este mismo registro quedará el residuo. El cociente se generará a lo largo del algoritmo, en un registro de desplazamiento a la izquierda se introducirá un dígito en cada iteración. Si el divisor “alcanzó” en el residuo, se introducirá por la izquierda un 1 al cociente y si no, se introducirá un 0. Al final del algoritmo, en este registro estará el cociente. En la figura 3.20 se muestra el hardware para la división y en la figura 3.21 se muestra el algoritmo que sigue el bloque de control. El algoritmo inicia con una resta y dependiendo del resultado se determina el valor del bit que se introducirá al cociente. Se requiere de 33 iteraciones por que en la primera no se está restando del dividendo, puesto que aún no se ha desplazado al divisor a la derecha. Fig. 3.20 Hardware para la división (primera versión) Fig. 3.21 Algoritmo para la división (primera versión) Ejemplo: Primer algoritmo de la división Usando números de 4 bits, para reducir espacio, dividir 7diez ÷ 2diez. (0111dos x 0010dos). Respuesta: Debido a que los números son de 4 bits, el algoritmo requerirá de 5 iteraciones, construiremos una tabla mostrando los diferentes pasos en cada iteración: Iteración Paso 0 Valores iniciales 1: Res. = Res. – Div. 1 2b: Res < 0 => +Div, Sll C, C0 = 0 3: Desp. Div. a la der. 1: Res. = Res. – Div. 2 2b: Res < 0 => +Div, Sll C, C0 = 0 3: Desp. Div. a la der. 1: Res. = Res. – Div. 3 2b: Res < 0 => +Div, Sll C, C0 = 0 3: Desp. Div. a la der. 1: Res. = Res. – Div. 4 2a: Res > 0 => Sll C, C0 = 1 3: Desp. Div. a la der. 1: Res. = Res. – Div. 5 2a: Res > 0 => Sll C, C0 = 1 3: Desp. Div. a la der. Cociente Divisor 0000 0010 0000 0000 0010 0000 0000 0010 0000 0000 0001 0000 0000 0001 0000 0000 0001 0000 0000 0000 1000 0000 0000 1000 0000 0000 1000 0000 0000 0100 0000 0000 0100 0001 0000 0100 0001 0000 0010 0001 0000 0010 0011 0000 0010 0011 0000 0001 Residuo 0000 0111 1110 0111 0000 0111 0000 0111 1111 0111 0000 0111 0000 0111 1111 1111 0000 0111 0000 0111 0000 0011 0000 0011 0000 0011 0000 0001 0000 0001 0000 0001 En cada iteración se subraya en el residuo al bit mas significativo, por que este bit determina si se continuará con el paso 2a o con el paso 2b (indica se el resultado de la resta es mayor o menor que cero). Segunda versión del Hardware de la División. Observando a la figura 3.20 y analizando con detalle el desarrollo del algoritmo, puede notarse que la parte significativa de la resta es de 32 bits, por que en los otros 32 se están restando 0s, por lo que la ALU que realiza las restas puede reducirse a 32 bits. Además, se consigue el mismo resultado si en lugar de desplazar el divisor a la derecha, éste se mantiene fijo y se desplaza al registro del residuo a la izquierda. Debe recordarse que al comienzo del algoritmo, el registro del residuo deberá contener al dividendo en sus 32 bits más a la derecha. En la figura 3.22 se muestra la segunda versión del hardware de la división; la resta se realiza entre los 32 bits más significativos del residuo y el divisor. No se muestra al algoritmo que sigue el control, por que prácticamente sería el mismo al mostrado en la figura 3.21, con la única diferencia que en el paso 3, en lugar de desplazar a la derecha al divisor, se desplazará a la izquierda al residuo. Fig. 3.22 Hardware para la división (segunda versión) Versión final del Algoritmo y Hardware de la División. El hardware mostrado en la figura 3.22 puede mejorarse si se observa que tanto el registro del cociente y el registro del residuo se desplazan a la izquierda, además en cada desplazamiento que realiza el registro del residuo, se introduce un 0 en el bit menos significativo, de manera que cuando el algoritmo termina, el residuo queda en los 32 bits más significativos, mientras que los 32 bits menos significativos quedan llenos de 0s. Entonces, el hardware puede modificarse de manera que los bits que se introduzcan sean los que correspondan al cociente, con ello, además de reducir un poco los recursos de hardware, produce un algoritmo más rápido, puesto que en lugar de realizar dos desplazamientos, sólo se realizará 1. Al final del algoritmo, en un registro de 64 bits se tendrá al residuo (en los 32 bits más significativos) y al cociente (en los 32 bits menos significativos). Una observación importante al algoritmo, es que en la primera iteración siempre a 0 se le resta el divisor, y la resta siempre será menor que 0, esta resta no tiene sentido. Por lo que es posible mejorarlo si antes de la primera resta se desplaza a la izquierda el residuo, con ello el número de iteraciones se reduce a 32, sin embargo, para compensar este desplazamiento inicial, al concluir las 32 iteraciones, los 32 bits más significativos deben desplazarse una posición a la derecha, para obtener el resultado correcto. En las figuras 3.23 y 3.24 se muestra la versión final del hardware y del algoritmo de la división respectivamente. Fig. 3.23 Hardware para la división (versión final) Fig. 3.24 Algoritmo para la división (versión final) Ejemplo: Versión final del algoritmo de la división Con la versión final del algoritmo, dividir 7diez ÷ 2diez. (0111dos x 0010dos). Respuesta: Con esta nueva versión sólo se requerirá de 4 iteraciones y en cada iteración se realizarán dos pasos: Iteración Paso 0 Valores iniciales Desp. Res. a la izq. 1 2: Res. = Res. – Div. 1 3b: Res < 0 => +Div, Sll R, R0 = 0 2: Res. = Res. – Div. 2 3b: Res < 0 => +Div, Sll R, R0 = 0 2: Res. = Res. – Div. 3 3a: Res > 0 => Sll R, R0 = 1 2: Res. = Res. – Div. 4 3a: Res > 0 => Sll R, R0 = 1 Desp. Mitad izq. de Rem. a la der. Divisor 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 Residuo 0000 0111 0000 1110 1110 1110 0001 1100 1111 1100 0011 1000 0001 1000 0011 0001 0001 0001 0010 0011 0001 0011 Después de las 4 iteraciones se desplaza a la izquierda la mitad izquierda del registro del residuo. En los 4 bits menos significativos se tiene al cociente. El hardware para la multiplicación es prácticamente el mismo que el hardware para la división, la diferencia estriba en el algoritmo de control. Los registros en los que se ubicará el resultado (en ambos casos) son conocidos como HI y LO. Al realizar una multiplicación, HI contendrá la parte alta del producto y LO la parte baja. En el caso de una división, HI quedará con el residuo, mientras que LO contendrá al cociente. 3.8 Números y operaciones Punto Flotante Otros tipos de datos importantes son los números de punto flotante, los cuales son una aproximación a los números reales. La mayoría de computadoras utilizan al estándar IEEE 754 el cual establece una representación de 32 bits para números en punto flotante en simple precisión y 64 bits para números en punto flotante en doble precisión (MIPS no es la excepción, también emplea ese formato). El estándar IEEE 754 representa a los números en notación científica normalizada (en base 2). La versión normalizada deja un dígito a la izquierda del punto decimal y los dígitos restantes se sitúan a la derecha; por ejemplo, el número: 0.000111, una vez normalizado es 1.11 x 2-4 y el número 11000000 al normalizarse queda como: 1.1 x 27, de manera que cualquier número puede ser aproximado con una expresión de la forma: 1.xxxxxxdos x 2yyyyyy A la cadena xxxxxx se le conoce como mantisa y a la cadena yyyyyy se le conoce como exponente. Pero además, los números en punto flotante pueden ser positivos o negativos, de manera que en la representación de un número debe considerarse un campo para el signo, un campo para el exponente y otro para la mantisa. De los 32 bits que se disponen en simple precisión, la distribución de los campos es: 31 signo 1 bit 30 29 28 . . . 24 23 Exponente 8 bits 22 21 20 19 . . . 3 2 1 0 Mantisa 23 bits Se han dedicado 8 bits para el exponente, lo que significa que se tienen 256 combinaciones, de las cuales deben considerarse algunas mayores y otras menores que cero, para representar números muy pequeños y números muy grandes. Sin embargo y debido a que es más fácil manipular números sin signo, las combinaciones se conservarán desde el valor 0 hasta el 255, y para obtener el valor representado, al valor del exponente se le restará un número conocido como desplazamiento. La mantisa corresponde a los dígitos que quedan a la derecha del punto decimal, después de la normalización. La representación contiene a un 1 que no se escribe por que todos los números normalizados lo incluirán. Entonces, a partir de los 32 bits (conteniendo 1s y 0s), el valor representado corresponderá a: (-1)signo x 1.mantisa x 2exponente - desplazamiento El valor del desplazamiento es de 127 para simple precisión, por lo que el número más cercano al cero se obtiene con una cadena de 32 ceros (correspondería a 1 x 2-127), y esta en el orden de 10-39. Por convención, esta combinación es interpretada como 0.0, puesto que en simple precisión no es posible encontrar un número mas cercano al 0. El número más alejado del 0, se obtiene con una cadena de 1s (a excepción del bit de signo, que puede tener 0). Esta combinación está en el orden de 1038, que aunque es un número grande, difiere de lo que consideramos como infinito. Las operaciones en punto flotante pueden producir resultados mas pequeños (bajo flujo) o resultados mas grandes (sobre flujo), por lo que en ocasiones será necesario contar con mas bits para la representación. El estándar IEEE 754 incluye una representación de doble precisión, la cual utiliza 64 bits, por lo que los tamaños de los campos crecen significativamente: 31 signo 1 bit 30 29 28 . . . 21 20 Exponente 8 bits 31 30 29 28 19 18 17 . . . 3 2 1 0 Mantisa 23 bits . . . Mantisa 32 bits 3 2 1 0 Para el campo del exponente se dispone de 11 bits, mientras que para la mantisa se tienen 52; con ello, el número mas cercano al 0 está en el orden de 10-308 y el mas alejado del 0 esta en el orden de 10308. Para obtener el valor que se está representando, se emplea la misma expresión utilizada en simple precisión, con la diferencia de que el valor del desplazamiento será de 1023. Ejemplo: Conversión de binario a decimal. ¿Qué número decimal representa la palabra? 1 signo 10000001 exponente 01000000000.... mantisa Respuesta: Aplicando directamente la expresión: (-1)signo x 1.mantisa x 2exponente – desplazamiento = (-1)1x1.0100dos x 2129 – 127 = - 1.01dos x 22 = - 101dos = - 5.0 diez Ejemplo: Representación en Punto-Flotante ¿Cuál sería la representación del –0.75diez en simple precisión? Respuesta: El número –0.75diez = -3/4 diez = -3/22 diez = -11dos / 22 diez = - 0.11dos En notación científica normalizada se tendría: - 1.1 x 2-1 Comparando con la expresión: (-1)signo x 1.mantisa x 2exponente – 127 se tiene que: exponente – 127 = -1, de manera que exponente = 127 – 1 = 126 Por lo tanto, la representación del –0.75diez es: 1 signo 01111110 exponente 1 0 0 0 0 0 0 0 0 0 0 0. . . . mantisa Suma en punto flotante. Para entender como sería el algoritmo y hardware para sumar números en punto flotante, repasaremos como se haría la operación si se tratase de números decimal. Sumaremos los números 9.999diez x 101 con 1.610diez x 10-1, suponiendo que sólo podemos almacenar cuatro dígitos decimales en la mantisa y dos en el exponente. a) Para que la suma sea correcta, primero se deben alinear los números adecuadamente, es decir, se debe buscar que el exponente sea el mismo para los dos números. Para ello, desplazaremos el número con el exponente mas pequeño para que alcance al del exponente mas grande: 1.610diez x 10-1 = 0.1610diez x 100 = 0.01610diez x 101 Pero como sólo podemos representar 4 dígitos en la mantisa, el número anterior se redondearía a: 0.016diez x 101 b) Ahora es posible sumar las mantisas: 9.999 diez + 0.016 diez 10.015 diez La suma es 10.015 x 101. c) Este resultado no esta normalizado, por lo que el siguiente paso consistiría en normalizarlo, para obtener: 1.0015 x 102. d) Finalmente, puesto que solo se pueden almacenar 4 dígitos para la mantisa, el resultado debe redondearse a 4 dígitos, el redondeo consiste en aproximar al número inmediato superior el penúltimo dígito, si el dígito menos significativo es mayor o igual a 5 y en caso contrario, aproximar al inmediato inferior. Obteniéndose como resultado final: 1.002 x 102 En el inciso (c) al normalizar la suma puede ocurrir un error de sobre flujo si el valor del exponente es mayor al que se puede representar o bajo flujo en caso de que sea menor. El algoritmo para la suma en punto flotante se muestra en la figura 3.25, en donde se muestra que después de un redondeo, puede ser necesaria otra normalización. La detección del sobre flujo o bajo flujo depende de la precisión que se este utilizando para la representación de los números. Fig. 3.25 Algoritmo para la suma en punto flotante Ejemplo: Suma en punto flotante. Sumar los números 0.5diez y –0.4375 diez en binario, usando el algoritmo de la figura 3.25 Respuesta: Primero obtendremos la versión binaria normalizada, suponiendo 4 bits de precisión: 0.5diez = 1/2 diez = 1/21diez = 0.1dos = 0.1dos x 20 = 1.000dos x 2-1 - 0.4375diez = - 7/16 diez = - 7/24diez = - 0.0111dos = 0.0111dos x 20 = - 1.110dos x 2-2 Ahora siguiendo el algoritmo: 1) Se desplaza al número con exponente mas pequeño (a la derecha), hasta alinearlo con el exponente mayor: - 1.110dos x 2-2 = - 0.111dos x 2-1 2) Se suman las mantisas: 1.000dos x 2-1 + (- 0.111dos x 2-1 ) = 0.001dos x 2-1 3) Se normaliza la suma, verificando si existe sobre flujo o bajo flujo: 0.001dos x 2-1 = 0.010dos x 2-2 = 0.100dos x 2-3 = 1.000dos x 2-4 Puesto que 127 > - 4 > - 126, no hay sobre flujo ni bajo flujo (El exponente desplazado sería – 4 + 127 = 123, y está entre 1 y 254). 4) Redondeo de la suma: 1.000dos x 2-4 Ya está redondeada, por lo que el resultado es: 1.000dos x 2-4 = 0.0001000dos = 1/24 diez = 1/16diez = 0.0625diez Muchas máquinas dedican hardware para ejecutar operaciones de punto flotante tan rápido como sea posible. En la figura 3.26 se esboza la organización básica del hardware para la suma en punto flotante. Multiplicación en punto flotante Una vez comprendida la suma, evaluaremos como se realiza la multiplicación en punto flotante. Iniciaremos con números decimales en notación científica. Multiplicaremos 1.110diez x 1010 con 9.200diez x 10-5. Supondremos que podemos almacenar solo 4 dígitos en la mantisa y 2 en el exponente. a) A diferencia de la suma, calcularemos el exponente del producto sumando los exponentes de los factores. Nuevo exponente = 10 + (-5) = 5 Probemos con los exponentes desplazados para asegurarnos que obtenemos el mismo resultado: 10 + 127 = 137, y –5 + 127 = 122, de manera que: Nuevo exponente = 137 + 122 = 259 El cual definitivamente es erróneo, el problema es que el desplazamiento se realizó dos veces (una por cada exponente), de manera que el exponente desplazado es: Nuevo exponente = (137 + 122) - 127 = 259 – 127 = 132 b) Luego se deben multiplicar las mantisas: 1.110diez x 9.200diez 0000 0000 2220 9990 10212000diez Fig. 3.26 Hardware requerido para la suma en punto flotante Hay tres dígitos a la derecha de cada factor, de manera que deberá haber 6 dígitos a la derecha del punto decimal del producto: 10.212000diez Suponiendo que sólo se pueden mantener 3 dígitos a la derecha del punto decimal, el producto resultante sería: 10.212diez x 105 c) Este resultado no esta normalizado, de manera que tenemos que normalizarlo para obtener: 1.0212diez x 106 Después de la multiplicación, el producto puede ser desplazado a la derecha, sumando 1 al exponente, o bien desplazado a la izquierda restándole 1 al exponente. Por lo tanto, en este paso debe verificarse la presencia de un sobre flujo o bien de un bajo flujo. d) Puesto que asumimos que la mantisa era de 4 dígitos, se debe redondear al producto, de manera que: 1.0212diez x 106 es redondeado a 1.021diez x 106 e) El signo del producto depende de los signos de los factores, si son iguales el producto es positivo y si son diferentes, el producto será negativo. En este caso el resultado es: + 1.021diez x 106 El signo en la suma fue determinado por la suma de las mantisas, pero en el producto el signo se determina por los signos de los operandos. En la figura 3.27 se muestra el algoritmo de multiplicación binaria en punto flotante. En donde se muestra que después de la normalización, es posible que ocurra un error de sobre flujo o bajo flujo; y después del redondeo, es posible que se requiera normalizar nuevamente. Fig. 3.27 Algoritmo para la multiplicación en punto flotante Ejemplo: Producto en punto flotante. Multiplicar 0.5diez x - 0.4375 diez en binario, usando el algoritmo de la figura 3.27. Respuesta: 0.5diez = 1.000dos x 2-1 - 0.4375diez = - 1.110dos x 2-2 Siguiendo el algoritmo: 1) Se suman los exponentes: -1 + (-2) = -3 2) Se multiplican las mantisas: 1.000 dos x 1.110 dos 0000 1000 1000 1000 1110000 dos El producto es 1.110000 dos x 2-3, pero necesitamos mantenerlo en 4 bits por lo que obtenemos: 1.110 dos x 2-3 3) El producto esta normalizado y no hay error de sobre flujo o bajo flujo. 4) El redondeo no cambia al producto. 5) Los signos de los operandos son diferentes, de manera que el resultado es: - 1.110 dos x 2-3 Instrucciones de Punto Flotante en MIPS MIPS soporta a los formatos del estándar IEEE 754 para simple y doble precisión, con las instrucciones: Suma en simple precisión (add.s) y en doble precisión (add.d) Resta en en simple precisión (sub.s) y en doble precisión (sub.d) Multiplicación en simple precisión (mul.s) y en doble precisión (mul.d) División en simple precisión (div.s) y en doble precisión (div.d) Comparación en simple precisión (c.x.s) y en doble precisión (c.x.d), donde x puede ser: igual (eq), no igual (neq), menor que (lt), menor o igual que (le), mayor que (gt) y mayor o igual que (ge) Brinco en punto flotante sobre una condición verdadera (bclt) y sobre una condición falsa (bclf). La comparación en punto flotante ajusta un bit a falso o verdadero, dependiendo de la condición de la comparación; y el brinco en punto flotante decide si se realizará o no el brinco, dependiendo de la condición. Los diseñadores de MIPS decidieron agregar un conjunto separado de registros de punto flotante, llamados $f0, $f1, $f2, . . .- usados ya sea para simple o doble precisión. Por lo tanto, también incluyeron instrucciones de carga en punto flotante (lwcl) y almacenamiento (swcl). Los registros base para las transferencias de datos en punto flotante continúan siendo registros enteros. El código MIPS para cargar 2 números de punto flotante de simple precisión, desde la memoria, para sumarlos y almacenar el resultado en memoria es: lwcl lwcl add.s swcl $f4, x($sp) $f6, y($sp) $f2, $f4, $f6 $f2, z($sp) Un registro en doble precisión en realidad se forma con dos registros consecutivos de simple precisión, usando el número par como el nombre del registro. TAREA 1. Escribir un programa, en cualquier lenguaje de alto nivel, que siga los pasos de la versión final del algoritmo de la multiplicación. Por simplicidad usar datos de 16 bits, los cuales se deberán pedir al usuario para almacenarse en 2 arreglos. Luego se seguirá al algoritmo paso a paso, para dejar el resultado en un arreglo de 32 bits. Para mayor claridad en el programa, utilizar funciones para la suma y los desplazamientos. 2. Construir una tabla donde se muestren los resultados de dividir al 13diez entre el 3diez, con base en el algoritmo mostrado en la versión final de la división. 3. Mostrar la representación binaria IEEE 754 en simple precisión para los números 10.5diez y –2/3diez. (En el último caso se obtendrá una aproximación). 4. Siguiendo los algoritmos de la suma y multiplicación en punto flotante, sumar y multiplicar los números: 6.42 x 101 y 9.51x 102. Tratar a los números en base 10 y suponer que sólo se tiene 4 dígitos para la mantisa (3 a la derecha del punto decimal).