530 likes | 867 Views
Organización y Estructura del Computador 1. Tema 2 – Representación de la información. Almacenamiento de la Información.
E N D
Organización y Estructura del Computador 1 Tema 2 – Representación de la información
Almacenamiento de la Información la representación de los datos en el computador usan un número limitado de bits, ya que un bit por sí mismo, salvo algunas señales de control, no ofrece mucha información, es por esto que la Unidad de almacenamiento del computador, “Memoria”, en lugar de acceder a bits individuales, usan como unidad de transferencia bloques de ocho bits, denominados bytes. Un programa a nivel de máquina visualiza la memoria como un gran arreglo, donde cada byte de memoria está identificado por un número único, conocido como su dirección.
Números binarios Nuestro sistema numérico natural es el decimal, como ya se mencionó, pero ahora vamos a estudiar la aritmética del computador, el cual siempre trabaja con dos tipos de números: enteros y en coma flotante (lo que en decimal se llama notación científica). Para comprender la aritmética del computador, se deben comprender primero los sistemas numéricos binario y hexadecimal.
Números binarios En el sistema binario sólo hay dos dígitos: 0 y 1. Los números se representan en base a 2. Cada dígito tiene un valor que depende de su posición. Los valores de cada posición se incrementan en potencias de dos de derecha a izquierda. Para convertir un número en binario a decimal debemos sumar los valores de cada posición que tenga dígito 1. Por ejemplo para convertir el número 1011 binario a decimal se realiza la siguiente operación: (1011)2= (1x23) + (0x22) + (1x21) + (1x20) = (11)10
Números binarios Para convertir un número de decimal a binario se realizan divisiones sucesivas entre 2 hasta obtener un cociente 0 y se toma el resto invertido. Por ejemplo para convertir el número 25 a binario se hace lo siguiente:
Sistema numérico hexadecimal En la notación hexadecimal hay 16 símbolos, es un sistema en base 16. La ventaja que presenta es el hecho de que cada dígito se representa en binario usando 4 dígitos binarios. Usamos la notación de C para denotar un número en hexadecimal: 0x. Ejemplo: 0x23 es el número 23 en hexadecimal.
Sistema numérico hexadecimal Para convertir un número decimal a hexadecimal, se divide repetidamente el número entre 16 tomando los restos de manera inversa. Por ejemplo para convertir el número decimal 423 en hexadecimal, el procedimiento es:
Sistema numérico hexadecimal Para convertir un número hexadecimal en decimal, se multiplica cada uno de los dígitos hexadecimales por la potencia de 16 apropiada. Por ejemplo, dado el número 0x7AF, se calcula su equivalente decimal como: (7*162) + (10*161) + (15*160) = 1792+160+15=1967
Sistema numérico hexadecimal Para convertir un número hexadecimal a binario se expande cada dígito a su representación en binario. Por ejemplo el número 0x173A4C se convierte a binario de la siguiente manera: Entonces 0x173A4C es 000101110011101001001100 en binario.
Sistema numérico hexadecimal • Para convertir un número binario a hexadecimal: • Se divide en grupos de cuatro bits cada uno. Si el total de número de bits no es un múltiplo de cuatro, se debe hacer que el grupo extremo izquierdo sea el que quede con menos de cuatro bits, y rellenarlo adecuadamente con ceros del lado izquierdo. • Se traduce cada grupo de cuatro bits al dígito hexadecimal correspondiente: Ejercicio: 1111001010110110110011 El número binario 1111001010110110110011 es 0x3CADB3 en hexadecimal.
Tamaños de los datos Los computadores y compiladores soportan múltiples formatos de datos usando maneras diversas para codificar dichos datos, tales como números enteros y números de punto flotante, así como longitudes diferentes. Por ejemplo, muchas máquinas tienen instrucciones para manipular solamente bytes, así como números enteros representados como cantidades de dos, cuatro y ocho bytes. También soportan números de punto flotante representados como cantidades de cuatro y ocho bytes. El número de bytes asignados para cada tipo de variable varía con la máquina y el compilador.
Tamaños de los datos Estos son algunos de los formatos de datos del lenguaje C. Los programadores deben esforzarse en hacer sus programas portables a través diferentes máquinas y compiladores. Un aspecto de portabilidad es hacer el programa insensible a los tamaños exactos de los diferentes tipos de datos.
Direccionamiento y ordenamiento de los bytes Para objetos de programa que abarcan múltiples bytes, debemos establecer dos convenciones: cuál será la dirección del objeto, y cómo se van a ordenar los bytes en la memoria. En prácticamente todas las máquinas, un objeto multibyte es almacenado como una secuencia contigua de bytes, con la dirección del objeto dado por la dirección más baja de los bytes usados. Por ejemplo, dada una variable x de tipo int que posee la dirección 0x100, los cuatro bytes de x serían almacenados en las posiciones de memoria 0x100, 0x101, 0x102 y 0x103.
Direccionamiento y ordenamiento de los bytes Para ordenar los bytes que representan un objeto, hay dos convenciones comunes. Algunas máquinas almacenan el objeto en la memoria ordenado desde el byte menos significativo al más significativo, mientras otras máquinas lo almacenan del byte más significativo al menos significativo. La convención donde el byte menos significativo viene primero se conoce como little endian. Esta convención es seguida por la mayor parte de las máquinas de la antigua Digital Equipment Corporation (ahora parte de la Compaq Corporation), así como por Intel
Direccionamiento y ordenamiento de los bytes La convención donde el byte más significativo viene primero se conoce como big endian. Esta convención es seguida por la mayor parte de las máquinas de la IBM, Motorola, y Sun Microsystems. Las convenciones no se establecen con precisión a lo largo de las fronteras corporativas. Por ejemplo, los computadores personales fabricados por IBM usan procesadores compatibles Intel y de ahí que sean little endian. Muchos chips de microprocesador, incluyendo el Alpha y el PowerPC de Motorola, pueden ejecutarse en ambos modos, determinándose la convención de ordenamiento de byte cuando es encendido el chip.
Direccionamiento y ordenamiento de los bytes Ejemplo de ordenamiento de los bytes para la variable x de tipo int con valor hexadecimal de 0x01234567, ubicada en la dirección 0x100:
Direccionamiento y ordenamiento de los bytes • Para la mayoría de los programadores de aplicaciones, los ordenamientos de bytes usados en sus máquinas son totalmente invisibles. Los programas compilados para cualquier clase de máquina dan resultados idénticos. Sin embargo, algunas veces el ordenamiento de byte se convierte en un problema. • Cuando los datos binarios se comunican sobre una red entre máquinas diferentes. Los datos producidos por una máquina little endian que serán enviados a una máquina big endian, o viceversa, conduciendo a los bytes dentro de palabras que están en orden inverso al del programa de recepción.
Direccionamiento y ordenamiento de los bytes Para evitar tales problemas, el código escrito para aplicaciones de red debe seguir convenciones establecidas para el ordenamiento de byte para asegurarse que la máquina que envía convierta su representación interna al estándar de la red, mientras que la máquina que recibe convierte el estándar de red a su representación interna.
Representación de cadenas de caracteres Una cadena en C es codificada como un arreglo de caracteres terminado en el caracter nulo (null caracter, es decir, el que posee el valor cero). Cada caracter es representado por alguna codificación estándar, siendo la más común el código de caracteres ASCII. La representación de una cadena de carateres sobre cualquier sistema que use el código de caracteres ASCII, será igual independientemente de las convenciones de ordenamiento de los bytes y del tamaño de la palabra. Como consecuencia de esto, los datos texto son más independientes de la plataforma que los datos binarios.
Representación de código Considere la siguiente función en C: 1 int sum(int x, int y) 2 { 3 Return x + y; 4 } Cuando este código es compilado sobre varias máquinas, se generan los siguientes códigos de máquina: GNU/Linux: 55 89 e5 8b 45 0c 03 45 08 89 ec 5d c3 NT: 55 89 e5 8b 45 0c 03 45 08 89 ec 5d c3 Sun: 81 C3 E0 08 90 02 00 09 Alpha: 00 00 30 42 01 80 FA 6B
Operaciones lógicas Tomaremos como referencia las operaciones logicas en lenguaje C. Cuando se utilizan estas operaciones un argumento con valor 0 representa el valor lógico FALSO y cualquier argumento mayor que 0 representa el valor lógico VERDADERO. Retornan 1 o 0 indicando un resultado de VERDADERO o FALSO, respectivamente.
Operaciones lógicas Ejemplo:
Operaciones lógicas Operaciones lógicas a nivel de bit en C Para determinar el resultado se debe realizar la operación al número en binario ya que estas operaciones afectan cada bit del argumento.
Representación de enteros Usualmente se representan números enteros sin signo o con signo. Cuando se usa la representación sin signo sólo se pueden representar números positivos, en cambio con la representación con signo se pueden representar números positivos y negativos. En las máquinas actuales la representación de enteros con signo se hace por el método de complemento a 2.
Representación de enteros Ejemplo de representación sin signo para enteros representados en 4 bits:
Representación de enteros • Para representar números con signo se utiliza el 0 para representar el positivo y el 1 para representar el negativo, en la posición más significativa del número en binario (la que se encuentra más a la izquierda del número). • Para representar un número positivo se coloca un cero en la posición más significativa (signo positivo) y luego se escribe el número en binario. • Para representar un número negativo se representa en complemento a 2 del positivo correspondiente.
Representación de enteros • Para calcular el complemento a 2 de un número, se invierten los "0"s por "1"s y los "1"s por "0"s y luego se le suma 1 al número. • Ejemplo de representación sin signo para enteros representados en 4 bits:
Representación de enteros Cuando tenemos un número en binario en complemento a 2 y necesitamos saber su valor en decimal basta con aplicarle complemento a 2 de nuevo para obtener el correspondiente valor. Por ejemplo para saber qué número representa 1110 (en complemento a 2), invertimos los bits: 0001 y sumamos 1: 0001 + 1 = 0010 lo cual es 2, por lo tanto la combinación 1110 representa -2.
Puntos a estudiar en esta próxima clase • Conversión entre números con signo y números sin signo • Expansión de un número • Truncado de un número • Suma Binaria • Operaciones con números en complemento a 2 • Representación de números fraccionarios
Conversión entre números con signo y números sin signo El lenguaje de programación C provee la capacidad de trabajar con variables con signo y sin signo. Los números se asumen con signo por defecto, para declarar tipos de datos sin signo se debe declarar explícitamente. Cuando se usan ambos tipos de variables en una misma expresión, C implícitamente convierte la variable con signo a una variable sin signo.
Conversión entre números con signo y números sin signo Ejemplo de valores con signo y sin signo para representaciones de 4 bits:
Expansión de un número • Para convertir un número sin signo a un tipo de datos de mayor tamaño simplemente se añaden ceros en las posiciones más significativas. • Para expandir un número con signo se extiende el bit de signo, copiando ese bit (el más significativo) a las nuevas posiciones libres del nuevo tipo de datos extendido. Es decir, en el caso de un número positivo se llena con ceros a la izquierda y en caso de un número negativo se llena con unos.
Expansión de un número Ejemplo de expansión de números en complemento a 2 de 8 bits a 16 bits:
Truncado de un número Cuando se trunca un número se desechan bits más significativos lo cual puede variar su valor. Ejemplo de truncado de números en complemento a 2 de 8 bits a 4 bits:
Suma Binaria Se efectúa exactamente en la misma forma que la suma de números decimales, siguiendo los mismos pasos generales. En la suma binaria solamente pueden ocurrir cuatro casos, los cuales se muestran en la siguiente tabla:
Suma de enteros sin signo Cuando se realiza la suma de enteros sin signo se hace exactamente igual a la suma binaria. Hay que tomar en cuenta que la suma de dos números de igual número de dígitos puede incurrir en acarreo y por lo tanto el resultado puede tener un dígito adicional. En algunos casos esto provoca desbordamiento.
Suma de números en complemento a 2 Cuando se realiza la suma entre dos números representados en complemento a 2 se siguen usando las reglas de la suma binaria pero si hay acarreo este se descarta. El desbordamiento ocurre cuando al sumar dos números del mismo signo el resultado es del signo opuesto. Ejemplos de sumas con números en complemento a 2 para representación de 4 bits:
Resta de números en complemento a 2 Para realizar la resta se obtiene el complemento a 2 del substraendo y se le suma al minuendo. Por ejemplo para realizar la resta de 7 – 3 se suma 7 + (-3), es decir, se calcula el complemento a 2 de 3 y se la suma al 7. Ejemplos para números de 4 bits:
Multiplicación y división de números en complemento a 2 La multiplicación y la división son operaciones complejas, existen varios algoritmos para ejecutarlas pero en todos los casos estas instrucciones tardan mucho tiempo ejecutándose. Una operación de multiplicación puede tardar 12 ciclos de reloj mientras una suma tarda típicamente 1 sólo ciclo. Una manera de optimizar el código es reemplazar operaciones de multiplicación y división por desplazamientos para reducir así el tiempo de ejecución.
Multiplicación y división de números en complemento a 2 La multiplicación por potencias de 2 se lleva a cabo desplazando el número hacia la izquierda. La operación de desplazamiento en C se escribe x << n donde x es la variable numérica y n es el número de posiciones. Por ejemplo para números de 4 bits sin signo:
Multiplicación y división de números en complemento a 2 La división entre potencias de dos se realiza de forma similar, pero hay que tomar en cuenta el signo cuando se desplaza hacia la derecha, si la representación es en complemento a dos y el número es negativo hay que llenar los espacios a la izquierda con 1. Algunos lenguajes de programación proveen dos tipos de desplazamiento a la derecha, lógico el cual siempre llena con ceros, y aritmético que llena con el bit de signo.
Multiplicación y división de números en complemento a 2 Ejemplo de divisiones entre potencias de 2 para números de 4 bits con signo (desplazamiento aritmético):
Representación de números fraccionarios Se puede representar un número fraccionario en binario tomando en cuenta que cada posición a la derecha de la coma es una potencia de 2-n Así el número en binario 0,11 tiene como valores 1x2-1 + 1x2-2 =0,5 + 0,25 = 0,75
Representación de números fraccionarios Los números cuyo valor no se describe con la fórmula k x 2n no se pueden representar exactamente sino a través de aproximaciones. Por ejemplo para representar 1/5 =0,2 la aproximación dependerá del número de bits disponibles. Con 4 bits disponibles para representar la parte fraccionaria se puede representar como 0,0011=0,1875. Una representación de punto fijo donde se destinen algunos bits para la parte entera y otros para la parte decimal no permite representar muchos números, por esta razón las máquinas actuales utilizan la representación en coma flotante, la cual es similar a la notación científica en decimal.
Representación de números fraccionarios La representación en coma flotante más utilizada es la definida en el estándar IEEE 754. Este estándar se desarrolló para facilitar la portabilidad de los programas de un procesador a otro. El estándar define un formato simple de 32 bits y uno doble de 64 bits. La base implícita es 2.
Representación de números fraccionarios • El bit de signo es de la mantisa la cual corresponde a la parte fraccionada. • Para valores de exponente desde 1 hasta 254 en el formato simple se representan números en coma flotante normalizados distintos de cero. • El exponente está sesgado, siendo el rango de exponentes de -126 a 127. • Un número normalizado debe contener un bit 1 a la izquierda de la coma binaria; este bit está implícito, dando una mantisa efectiva de 24 bits. • Un exponente cero junto con una fracción cero representa el cero positivo o negativo, dependiendo del bit de signo. • Un exponente todo unos junto con una parte fraccionaria cero representa, dependiendo del bit de signo, el infinito positivo o negativo.
Representación de números fraccionarios • El número es positivo o negativo dependiendo del bit de signo. • Los números denormalizados se incluyen en el estándar para reducir las situaciones de desbordamiento hacia cero de exponentes. Cuando el exponente del resultado es demasiado pequeño el resultado se denormaliza desplazando a la derecha la parte fraccionaria e incrementando el exponente hasta que esté dentro de un rango representable. • A un exponente de todos unos junto con una fracción distinta de cero se le da el nombre de NaN (not a number, no representa un número) y se emplea para señalar varias condiciones de excepción.
Representación de números fraccionarios • Casos más frecuentes para formato simple: