ASM POR AESOFT. (lección 9). * Dedicada a Xavi * -------------------------------------------------------------------- - BASES NUMERICAS (DECIMAL, BINARIA, ETC...) - CAMBIO DE BASE - REPRESENTACION NUMERICA: Rango, Resolución, etc... * Coma fija sin signo (Binario Puro). * Complemento a 2. * BCD. -------------------------------------------------------------------- Hola de nuevo a todos los seguidores del CURSO DE ASM. En esta lección vamos a tratar un tema muy importante en programación, como es el empleo de determinadas bases numéricas (binaria y hexadecimal) para la representación de la información. Al finalizar la lección tendremos claro (eso espero :-) cómo se almacena un dato en la memoria, entenderemos por qué determinados tipos de datos (tipo byte, tipo palabra, etc..) admiten un rango de representación determinado, así como una resolución determinada, sabremos operar en bases diferentes a la decimal (base 10), etc, etc... --- El Rango de representación es el intervalo comprendido entre el menor número representable y el mayor. Así por ejemplo, el rango del tipo de dato byte es 0..255. Es decir, se pueden representar números desde el 0 al 255. El rango del tipo de dato palabra (Word) es 0..65535. Lo que es lo mismo, se pueden representar números comprendidos entre el 0 y el 65535, ambos inclusive. --- La resolución de la representación es la diferencia numérica que existe entre un número representable y el inmediatamente siguiente. - BASES NUMERICAS ----------------- Antes de entrar de lleno en las bases 2 y 16 que son las bases con las que trabaja el ordenador (en realidad el ordenador sólo trabaja en base 2, la base 16 se utiliza de cara al programador para compactar el número resultante de utilizar la base 2, que sería muy largo y engorroso para utilizar constantemente en los programas)... ... antes de meternos de lleno con éstas bases, como os decía, nos sería muy útil para su entendimiento el saber del porqué de la base decimal. * Base Decimal (Base 10). Es la base a la que estamos acostumbrados desde siempre, la base numérica más utilizada. En esta base 10, contamos con 10 dígitos: 0,1,2,3,4,5,6,7,8 y 9. Mediante estos 10 dígitos podemos expresar cualquier número que deseemos. El sistema de numeración decimal (base decimal) es un sistema de numeración posicional, al igual que los restantes sistemas que vamos a ver (binario, hexadecimal,etc), y a diferencia del sistema de numeración romano, por ejemplo. Un sistema posicional es aquel en el que un número viene dado por una cadena de dígitos, estando afectado cada uno de estos dígitos por un factor de escala que depende de la posición que ocupa el dígito dentro de la cadena dada. Es decir, que el dígito 9, valdrá 9 si está al final de la cadena, en la posición reservada para las unidades; valdrá 90 si el dígito se encuentra en la posición reservada para las decenas (2ª posición de derecha a izquierda); valdrá 900 si el dígito se encuentra en la posición reservada para las centenas; etc, etc... A esto es a lo que se le llama posicional, dependiendo de la posición que ocupe un dígito dentro de la cadena numérica, tendrá un valor o tendrá otro. Así por ejemplo, el número 8346 se podría descomponer como sigue: 8346 = (8 * 10^3) + (3 * 10^2) + (4 * 10^1) + (6 * 10^0) El factor de escala de que hablábamos arriba, son las diferentes potencias de 10 que multiplican a un dígito dependiendo de su posición dentro de la cadena numérica. Ahora nos podríamos preguntar por qué tenemos como sistema de numeración usual al sistema decimal, por qué es el más usado por todo tipo de gente, a qué se debe que en todo el mundo sea el sistema utilizado por las personas (ya veremos que las máquinas no usan el sistema decimal, sino el binario). Pues es bien sencillo: Porque tenemos 10 dedos. :-) Aún recordaremos eso que nos decían (a quién no?) en clase cuando empezábamos a contar, sumar, etc.. : No vale contar con los dedos! Intuitivamente, utilizábamos nuestra elemental calculadora: las manos, para contar, realizar sumas y restas sencillas, etc. * Base Binaria (Base 2). En esta base sólo contamos con 2 dígitos: 0 y 1. Al igual que la base decimal tiene su razón de ser, la base 2 o binaria tampoco ha surgido debido a un mero convencionalismo, sino que se basa en algo concreto: Electricidad. Toda la información que se manipula dentro de un ordenador se hace de acuerdo a señales eléctricas. Es lo único que entiende el ordenador. Mediante una señal eléctrica alta, se representa el valor 1; mediante una señal eléctrica baja se representa el 0. . (1) : Tensión eléctrica alta. . (0) : Tensión eléctrica baja. Todo el trabajo del procesador, buses, etc... se realiza de acuerdo a este sistema binario. Cuando se recibe una señal eléctrica alta, se interpreta como que ha llegado un dato de valor (1). Cuando la señal es baja, el dato es un (0). Todo el flujo de datos en el interior del ordenador, y del ordenador con los periféricos, se realiza mediante estas informaciones eléctricas. Para representar cadenas numéricas, se emplean cadenas de señales eléctricas. Así por ejemplo, para representar el número 10001101 (base 2), el ordenador utilizaría la cadena de señales eléctricas: Tensión alta, Tensión baja, Tensión baja, Tensión baja, Tensión alta, Tensión alta, Tensión baja, Tensión alta. El factor de escala en esta base, son las potencias de 2 que afectan a un dígito dado dependiendo de su posición en la cadena numérica. Obsérvese que al decir potencias de 2, me estoy refiriendo a potencias de 2 (en base 10). Es decir, para obtener la traducción de ese número en base 2 a su valor correspondiente en base 10, utilizamos las potencias de 2 mencionadas. Estas potencias de 2 en base 10, serían potencias de 10 en base 2. Es decir, el número 10 en base 2 equivale al número 2 en base 10. Veámoslo más claro. El número 10100101 se puede traducir a base 10 como: 10100101 = (1*2^7)+(0*2^6)+(1*2^5)+(0*2^4)+(0*2^3)+(1*2^2)+(0*2^1)+(1*2^0). O lo que es lo mismo: 10100101 (base 2) = 128+0+32+0+0+4+0+1 (base 10) = 165 (base 10) * Base hexadecimal (Base 16). Como hemos mencionado al principio de la lección, la base hexadecimal surgió para compactar la información binaria. Se utiliza un dígito hexadecimal para representar una cadena de 4 dígitos binarios. Teniendo en cuenta que con 4 dígitos binarios podemos representar 16 números diferentes: 0,1,10,11,100,101,110,111,1000,1001,1010, etc... ...Teniendo en cuenta esto, un dígito hexadecimal tiene que poder tomar 16 valores diferentes. Para la base 10, tenemos 10 dígitos diferentes: del 0 al 9; para la base 2, nos servimos de dos de esos dígitos que ya teníamos para la base 10: el 0 y el 1. Pero en la base 16, que tenemos 16 dígitos diferentes, no podemos valernos sólo de los dígitos de la base decimal, ya que sólo hay 10 diferentes, y necesitamos 16. La solución es utilizar letras para representar los 6 dígitos que nos faltan. Tenemos entonces que los dígitos hexadecimales son: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E y F. A equivale a 10 en base 10. B equivale a 11 en base 10. C equivale a 12 en base 10. D equivale a 13 en base 10. E equivale a 14 en base 10. F equivale a 15 en base 10. Del mismo modo que en la base 10, el último dígito es el 9; en la base 2, el último dígito es el 1; en la base 16, el último dígito será F. Si sumamos a F una unidad, obtendremos el número 10 (base hexadecimal). Este número 10h (se utiliza el sufijo 'h' para indicar que se trabaja con base hexadecimal, al igual que el sufijo 'b' indica que se está trabajando con base binaria) equivale a 16 en base 10. El factor de escala en esta base, son las potencias de 16 que afectan a un dígito dado dependiendo de su posición en la cadena numérica. De forma similar que al hablar de la base binaria, al decir potencias de 16, me estoy refiriendo a potencias de 16 (en base 10). Es decir, para obtener la traducción de ese número en base 16 a su valor en base 10, utilizamos las potencias de 16 mencionadas. Estas potencias de 16 en base 10, serían potencias de 10 en base 16. Es decir, el número 10 en base 16 equivale al número 16 en base 10. ¿Difícil de entender? Vamos a ver si esto lo aclara: El número AF34h se puede traducir a base 10 como: AF34 (base 16) = (10*16^3)+(15*16^2)+(3*16^1)+(4*16^0) (base 10). O lo que es lo mismo: AF34 = (10*4096)+(15*256)+(3*16)+4 = 40960+3840+48+4 = 44852 Hemos dicho que la base hexadecimal tiene como finalidad compactar la información binaria. 4 dígitos binarios se puden compactar en un sólo dígito hexadecimal. Tomemos por ejemplo el número 1010000101010101b. Nos es más fácil indicar este número mediante su correspondiente número en base hexadecimal. Compactamos entonces toda esa cadena de información binaria en sólo 4 dígitos de información en base hexadecimal. El proceso para llevar a cabo este cambio es sencillo. De derecha a izquierda de la cadena numérica, se van cogiendo cadenas de 4 dígitos binarios, y se transforman a su correspondiente dígito hexadecimal. Cojamos los primeros 4 dígitos binarios: 0101. 0101 (base 2) = (0*8) + (1*4) + (0*2) + (1*1) = 5 (base 16). Siguiendo el proceso con el resto de la cadena, tenemos que el número resultante en base 16 es A155h, que es mucho más fácil de recordar y almacenar (en cuanto a código fuente se refiere) que el correspondiente en base 2. En caso de que el número en binario tenga menos de 4 dígitos, se rellenan las posiciones que faltan hacia la izquierda con ceros. Es decir, si tenemos el número 100101b, al pasarlo a base hexadecimal, tenemos el dígito de las unidades 5 (0101b), y para el dígito de las decenas tenemos que encontrar el correspondiente hexadecimal a la cadena 10b, que es lo mismo que 0010b, O sea 2 en hexadecimal. Tenemos entonces que 100101b = 25h. Veamos una muestra de números en las tres bases mencionadas para ver sus equivalencias: ¦ Decimal Binario Hexadecimal ¦ ------- ------- ----------- ¦ 0 0 0 ¦ 1 1 1 ¦ 2 10 2 ¦ 3 11 3 ¦ 4 100 4 ¦ 5 101 5 ¦ 6 110 6 ¦ 7 111 7 ¦ 8 1000 8 ¦ 9 1001 9 ¦ 10 1010 A ¦ 11 1011 B ¦ 12 1100 C ¦ 13 1101 D ¦ 14 1110 E ¦ 15 1111 F ¦ 16 10000 10 ¦ 32 100000 20 ¦ 40 101000 28 ¦ 64 1000000 40 ¦ ¦ [...] [.....] [...] * Base octal (Base 8). Al igual que la base hexadecimal, se utiliza para compactar información binaria, pero en este caso, la compactación es menor, de tal manera que casi no se usa. Mientras que en la base hexadecimal con un sólo dígito se puede representar una cadena de 4 dígitos binarios, en la base octal un dígito sólo puede representar 3 dígitos binarios. Los dígitos posibles para la base octal, evidentemente, son los que van del 0 al 7. No profundizaremos más en esta base, ya que es totalmente similar a la base 16, y no se suele utilizar. - CAMBIO DE BASE ---------------- A continuación se detalla el procedimiento para obtener el equivalente de un número en cualquiera de las bases expuestas. Voy a prescindir de dar la teoría del método, para verlo directamente en la práctica. Tomemos un número dado en cada una de las diferentes bases. Por ejemplo el número 18732 en base decimal, que es 492C en base hexadecimal, y 100100100101100 en base 2. Veamos cómo se llega de uno de esos números a otro, al cambiar de base. * Cambio de base 2 a base 10. 100100100101100b = (1*2^14)+(1*2^11)+(1*2^8)+(1*2^5)+(1*2^3)+(1*2^2)= = 16384+2048+256+32+8+4 = 18732 (base 10). * Cambio de base 10 a base 2. ¦ 18732:2 ¦ ¦0¦ 9366:2 ¦ +-+ ¦0¦ 4683:2 ¦  +-+ ¦1¦ 2341:2 ¦  +-+ ¦1¦ 1170:2 ¦  +-+ ¦0¦ 585:2 ¦  +-+ ¦1¦ 292:2 ¦  +-+ ¦0¦ 146:2 ¦  +-+ ¦0¦ 73 :2 ¦  +-+ ¦1¦ 36 :2 ¦  +-+ ¦0¦ 18 :2 ¦  +-+ ¦0¦ 9 :2 ¦  +-+¦1¦ 4 :2 ¦  +-+¦0¦ 2 :2 ¦  +-+¦0¦ 1 :2 ¦  +-+¦1¦ 0 ¦  +-+ Partiendo del último resto de las sucesivas divisiones, y hasta llegar al primero, obtenemos: 100100100101100b, que es el equivalente en base 2 del número 18732 en base 10. * Cambio de base 2 a base 16. 100100100101100b = 100 1001 0010 1100 = 492C en base 16. (4) (9) (2) (C) * Cambio de base 16 a base 2. 492Ch = 0100 1001 0010 1100 = 100100100101100 en base 2. * Cambio de base 16 a base 10. 492Ch = (4*16^3)+(9*16^2)+(2*16^1)+(12*16^0)= = (4*4096)+(9*256)+(2*16)+(12) = = 16384+2304+32+12 = 18732 en base 10. * Cambio de base 10 a base 16. ¦ 18732 :16 ¦ ¦12 ¦ 1170 :16 ¦ ¦(C)¦ ¦2¦ 73 :16 ¦ +---+ +-+ ¦9¦ 4 :16 ¦  +-+ ¦4¦ 0 ¦  +-+ Partiendo del último resto de las sucesivas divisiones, y hasta llegar al primero, obtenemos: 492Ch, que es el equivalente en base 16 del número 18732 en base 10. Por supuesto, para automatizar el proceso de cambio de bases, existen calculadoras especiales, que permiten trabajar con diferentes bases, permiten representar en cada una de esas bases, realizar operaciones lógicas con los números, etc. En la lección anterior se ha hablado de este tipo de programas, así que no haré más incapié en lo sucesivo. - REPRESENTACION NUMERICA. -------------------------- A continuación vamos a ver las dos formas básicas de trabajar con valores números en ensamblador. Dependiendo de que trabajemos sólo con números naturales (enteros positivos, incluido el Cero), utilizaremos el sistema de representación binario puro. Si trabajamos con números enteros en general (positivos y negativos), se utiliza el complemento a 2. Además de estos dos sistemas de representación, veremos un tercero: El famoso BCD, que sirve para codificar y decodificar rápidamente información decimal (con la que estamos familiarizados) en una base binaria a la que no estamos tan acostumbrados. Aparte de los tres sistemas de representación numérica mencionados, hay varios más, como son: signo-magnitud, complemento a 1, etc, etc... que no vamos a tratar ahora, ya que o bien unos no son usados en el Pc, o bien son tan complejos de usar que se salen de la finalidad de este curso, al menos por el momento. * Coma fija sin signo (Binario Puro). Es el sistema usado para representar números enteros positivos. Este es un sistema de representación posicional con base 2 (binario), sin parte fraccionaria, y que sólo admite números positivos. Mediante este sistema se pueden representar (para un tipo de dato de longitud N) todos los enteros positivos desde 0 hasta (2^N)-1. Tenemos entonces que su rango es [0..(2^N)-1] y su resolución es la unidad (1), ya que trabajamos con enteros. Antes de estudiar este sistema con los tipos de datos propios del ensamblador, y por tanto del ordenador, vamos a hacer un estudio del mismo con un tipo de dato general, para así comprender perfectamente y sin lugar a dudas la base de este sistema, sus características, etc. Tomemos una cadena numérica de longitud 2, es decir, dos dígitos. Con este sistema vamos a poder representar todos los enteros positivos en el rango [0..(2^2)-1] = [0..3]. Es decir, mediante esta cadena numérica de 2 bits de longitud, podremos representar 4 números enteros positivos diferentes: ¦ Cadena numérica: XX ¦ -- ¦ Números posibles: 00 ¦ : 01 ¦ : 10 ¦ : 11 Si la cadena numérica fuese de 1 sólo dígito, sólo podríamos representar 2 números distintos: 0 y 1. En definitiva se trata de un sólo bit. Tomemos ahora una cadena de 3 bits o dígitos de longitud (N=3). En este caso podremos representar todos los enteros positivos en el rango [0..(2^3)-1] = [0..7]. Es decir, todos los números enteros comprendidos entre 0 y 7. Veamos ahora este sistema de representación con los 3 tamaños de datos básicos en el Pc: - Tamaño Byte (8 bits). La longitud de este tipo de dato es de 8 bits, es decir, N=8. Por tanto en este tipo de datos (y con el sistema de representación Binario Puro), vamos a poder representar enteros comprendidos en el Rango [0..(2^8)-1] = [0..255]. Esto quiere decir que en un registro o posición de memoria de tamaño byte (8 bits), vamos a poder tener 256 valores diferentes. - Tamaño Word ó palabra (16 bits). La longitud de este tipo de dato es de 16 bits. Por tanto en este tipo de datos (y con el sistema de representación Binario Puro), vamos a poder representar enteros comprendidos en el Rango [0..(2^16)-1] = [0..65535]. Esto quiere decir que en un registro o posición de memoria de tamaño palabra (16 bits), vamos a poder tener 65536 valores diferentes. O sea, que el mayor número que se podrá representar en este tamaño de dato, con este sistema de representación es el 65535; y el menor número representable será el 0. - Tamaño DWord, Double Word, ó Doble palabra (32 bits). La longitud de este tipo de dato es de 32 bits. Por tanto en este tipo de datos (y con el sistema de representación Binario Puro), vamos a poder representar enteros comprendidos en el Rango [0..(2^32)-1] = [0..4294967295]. * Complemento a 2. El sistema de representación Complemento a 2, es el usado por el Pc (entre otras cosas) para poder realizar sumas y restas con números enteros sin tener que hacer comprobaciones del signo de los operandos. Es decir, la instrucción ADD AX,BX se ejecutará igual si los números son positivos, que si son negativos, que si uno es positivo y otro negativo. Veamos las características de este sistema de representación desde un punto de vista práctico, para entenderlo mejor y más rápido: Supongamos que estamos trabajando con el tipo de dato Byte (8 bits), luego N (longitud de la cadena numérica) es igual a 8. Si estuviéramos trabajando sólo con números enteros positivos (binario puro), el registro ó posición de memoria admitiría 256 valores positivos. Pero estamos utilizando el sistema de Complemento a 2, porque vamos a trabajar con enteros en general, positivos y negativos. Luego esos 256 valores han de dividirse en 2 grupos: uno para los positivos, y otro para los negativos. Para los números positivos se reservan los códigos que tengan el bit 7 (bit más significativo, ya que estamos trabajando con datos de 8 bits) con valor 0. Es decir, los códigos 00000000 hasta 01111111. El resto de códigos posibles se utilizan para representar los números negativos. Es decir, los códigos 10000000 hasta 11111111. Es fácil determinar de esta forma si un número es positivo o negativo. Si es positivo, su bit más significativo valdrá 0. Si es negativo, su bit más significativo valdrá 1. Hemos visto los códigos reservados para cada grupo de números, los positivos y los negativos. Veremos a continuación las diferencias en la representación entre los positivos y los negativos: Los números positivos se representan en binario puro, como hemos visto en el apartado anterior. Es decir, si queremos representar el número 37 en un registro de tipo byte, quedaría de la forma 00100101. Como podemos observar, al utilizar números positivos en Complemento a 2, estamos utilizando la representación en Binario Puro. Hay que tener en cuenta el mayor número positivo representable en este tipo de dato (8 bits) y con este sistema de representación. Es decir, no se pude representar números positivos más allá del 01111111b, por tanto el mayor número positivo representable es el 127 para este tamaño de dato byte. Todo lo expuesto hasta ahora (y a continuación) para el tipo de dato byte, es extensivo para el resto de tipos de datos (palabra y doble palabra), teniendo en cuenta su diferente longitud (N), obviamente. En general, el rango de representación de los números positivos en el sistema de complemento a 2 es: [0..(2^(N-1))-1] ¦ En el caso de dato de tipo byte: [0..(2^(8-1))-1] ¦ [0..(2^7)-1] ¦ [0..128-1] ¦ [0..127] ¦ ¦ Para el tipo de dato word: [0..(2^(16-1))-1] ¦ [0..(2^15)-1] ¦ [0..32768-1] ¦ [0..32767] ¦ ¦ Etc.... Con los números negativos es cuando sí se utiliza el Complemento a 2. Para representar un número negativo hay que realizar el complemento del número de la siguiente manera: Hay que restar el módulo del número negativo a representar de 2^N. Por ejemplo: Para ver cómo quedaría el número -108 en un registro de tipo byte, haríamos lo siguiente: Tenemos una longitud de dato de 8 bits, luego N=8 y por tanto, 2^N=256. Ahora restamos a 256 el módulo de (-108). Es decir, le quitamos a 108 su signo, y lo restamos de 256. ¦ 256 100000000 ¦ -108 - 1101100 ¦ ---- --------- ¦ 148 10010100 ¦ ¦ ¦ +- Observamos que el bit de más a la ¦ izquierda tiene valor 1, indicando ¦ que se trata de un número negativo. A estas alturas, podremos apreciar que para representar un número negativo en complemento a 2, no introducimos ese número en el registro ó posición de memoria, sino su complemento con respecto a 2^N. De esta manera, todos los números negativos tendrán su bit más significativo con valor 1, indicando su condición de número negativo. Para obtener el rango de los números negativos, tenemos que calcular el mínimo y el máximo representable. Tomemos el tipo de dato byte, para concretar: El más pequeño número negativo es -1, y su complemento es 11111111. Como en los números negativos, el bit más significativo (bit 7 en este caso) debe ser 1, el máximo negativo representable será el máximo al que se le pueda hacer el complemento sin que el bit más significativo sea 0, ya que entonces sería positivo. Llegamos entonces a la conclusión de que tal máximo es -128, con el complemento 10000000b. En general, el rango de representación de los números negativos en el sistema de complemento a 2 es: [-(2^(N-1))..-1] ¦ En el caso de dato de tipo byte: [-(2^(8-1))..-1] ¦ [-(2^7)..-1] ¦ [-128..-1] ¦ ¦ Para el tipo de dato word: [-(2^(16-1))..-1] ¦ [-(2^15)..-1] ¦ [-32768..-1] ¦ ¦ Etc.... El rango completo de representación (negativos y positivos) en el sistema de Complemento a 2 es: [-(2^(N-1))..(2^(N-1))-1]. Siendo N, la longitud del dato. Veamos algunos ejemplos de representación para comprenderlo definitivamente... Ejemplo: Cómo se representará el número -7 en un registro de tamaño word? Tamaño word = 16 bits de longitud, luego N=16, y por tanto 2^N=65536. ¦ 65536 10000000000000000 ¦ - 7 - 111 ¦ ----- ----------------- ¦ 65529 1111111111111001 ¦ ¦ ¦ +- Bit más significativo con valor 1, indicando ¦ número negativo. Ejemplo curioso: Supongamos que estamos trabajando con un tipo de dato byte. El número 10000000b representado en binario puro es 128, y representado en Complemento a 2, sería -128. Probad a realizar el complemento y obervaréis que el complemento de 10000000b es el mismo 10000000b (con N=8, claro). Como creo que para alguien que ha visto esto por primera vez, le resultará difícil de entender, y es posible que con lo expuesto hasta ahora no lo tenga del todo claro, me extenderé un poco más: Lo que viene a continuación es el quid de la cuestión de la representación en Complemento a 2. Tomemos el registro AL, por ejemplo. Si AL = 10010101, tenemos dos números diferentes dependiendo de que estemos teniendo en cuenta los números negativos o no. Esto es, dependiendo de si estamos trabajando en binario puro o en complemento a 2. Es decir, en binario puro, el número 10010101 es 149 en base decimal. Mientras que si estamos basándonos en el Complemento a 2, el número que tendríamos ya no sería un 149, sino que sería un número negativo por tener su bit más significativo con valor 1. Más concretamente se trataría del número -107. Para obtener el número negativo del que se trataba, hacemos el complemento a 2. Como el número ya estaba en complemento a 2, complemento con complemento se anulan, y obtenemos el original número negativo que es -107. Es decir, 256-149=107. Ahora le ponemos el signo, y tenemos el -107. Hemos visto, pues, que dependiendo de que tengamos en cuenta (Complemento a 2) ó No (Binario Puro) el signo de un número, éste podrá tener 2 valores diferentes, el número positivo, y su complementario negativo. Pero esto sólo sucede, obviamente, con los números que tienen el bit más significativo con valor 1. Si tomamos por ejemplo el número 3, dará igual que estemos trabajando con binario puro o complemento a 2, tendremos en ambos casos el número positivo 3, ya que el bit más significativo al ser 0, no deja la posibilidad de ser un número negativo. Hemos dicho arriba que el ordenador utiliza el sistema de Complemento a 2 por la comodidad que le supone para realizar las sumas y las restas. Veamos cómo lleva a cabo el ordenador estas operaciones, y así entenderemos mejor el porqué de este sistema de representación. Supongamos que queremos sumar los registros AL y CL. Estamos trabajando en nuestro programa con números positivos y negativos, con lo cual el sistema de representación que tenemos que tener presente es el de Complemento a 2. Démosle valores a AL y CL: AL=-37. CL=120. Tenemos pues un número negativo y otro positivo. Veamos cómo se representan ambos números en sus respectivos registros, teniendo en cuenta las características de la representación en Complemento a 2. AL=11011011 CL=01111000 Como podemos observar, en AL tenemos el número en Complemento a 2, mientras que en CL, el número quedaría como binario puro. Tras realizar la suma (ADD AL,CL), en AL deberá quedar el valor 83, positivo, por supuesto. Veamos si es así. Realicemos la suma: ¦ AL=11011011 ¦ + CL=01111000 ¦ ------------- ¦ 101010011 ¦ ¦ ¦ +--Este bit se desprecia, ya que se sale del registro de ¦ 8 bits. Ocuparía una novena posición que no hay. ¦ Tenemos entonces AL=01010011. Veamos el equivalente de 01010011b en base decimal. Para que la operación sea correcta, deberíamos obtener el valor 83 = ((-37)+120). Haced ese cambio de base que os digo, y obtendreis el resultado que esperábamos (83). Supongamos ahora que queremos sumar los registros AL y CL de nuevo, pero esta vez estamos trabajando con dos números positivos, con lo cual, el sistema de representación que nos interesa es el de Binario Puro. En esta ocasión, CL tiene el mismo valor que antes, CL=120. Pero AL que ahora es un número positivo tiene un valor al azar, por ejemplo el valor 219. AL=219 CL=120 Tenemos pues, dos números positivos. Veamos cómo se quedarían ambos números en sus respectivos registros. AL=11011011 CL=01111000 ¡¡¡Qué casualidad!!! :-) ¡¡¡Pero si tienen los mismos valores que en el ejemplo anterior!!! Tengamos en cuenta en este caso, que al realizar la suma vamos a obtener desbordamiento, ya que 120+219=339 que sobrepasa el valor 255 (máximo número representable en binario puro para un tipo de dato de 8 bits). Ese 339 en binario sería 101010011. Los bits que caben en el registro son los 8 de la derecha: 01010011, que en base decimal es 83!!! Veamos si es así. Realicemos la suma: ¦ AL=11011011 ¦ + CL=01111000 ¦ ------------- ¦ 101010011 ¦ ¦ ¦ +--Este bit se desprecia, ya que se sale del registro de ¦ 8 bits. Ocuparía una novena posición que no hay. ¦ Esto lo indica el procesador mediante el flag de Overflow ¦ Of. ¦ Y el registro nos queda con el contenido AL=01010011. 01010011b en base decimal es 83 como hemos indicado arriba. Mediante estos dos casos prácticos, llegamos a la conclusión del valor que tiene el sistema de representación Complemento a 2. Os sugiero que si aún queda algún ápice de duda en cuanto a este sistema de representación usado por el ordenador para representar los números negativos, os pongais vuestros propios ejemplos: Suma de número negativo y número negativo. Resta de número negativo y número positivo. Resta de número negativo y número negativo. Etc... De esta forma, se comprenderá de forma práctica el sistema de representación numérica que usa el Pc para estos números enteros, y el porqué del mismo. Para finalizar con el apartado de Complemento a 2, veamos unos ejemplos de representación para unos valores dados, en los que se comparan las representaciones Binario Puro y Complemento a 2. En este caso, estos valores se van a encontrar almacenados en un registro de 8 bits (tamaño byte), por ejemplo AL. Contenido de AL Binario Puro Complemento a 2 --------------- ------------ --------------- 00000000 0 0 00000001 1 1 00000010 2 2 00000101 5 5 00100000 32 32 00111101 61 61 01111111 127 127 10000000 128 -128 10000001 129 -127 10000111 135 -121 10111111 191 -65 11111110 254 -2 11111111 255 -1 * BCD (Sistema Decimal codificado en Binario). Este sistema BCD, sirve (como hemos mencionado antes) para codificar y decodificar rápidamente información decimal en una base binaria. Se utiliza un byte para almacenar cada dígito decimal. Es decir, mediante este método no se realiza la traducción de una cadena numérica en base decimal a la base binaria propia del ordenador, sino que se almacena como una cadena de bytes, uno de ellos para cada dígito de la cadena decimal introducida. Mientras que el número 133 en base decimal se almacena en un sólo byte utilizando el sistema de representación Binario Puro, necesitará 3 bytes para ser representado en BCD. La representación en BCD sería la cadena de bytes '1','3','3'. Es decir, los bytes con código ASCII 31h,32h,33h. El número 23849 necesitaría sólamente 2 bytes (una palabra) para ser representado en Binario Puro, mientras que en BCD necesitaría 5 bytes, uno para cada dígito decimal. 32h,33h,38h,34h,49h. Lo expuesto hasta ahora sobre el sistema BCD, tiene un carácter orientativo. En esta lección no abordaremos en detalle este sistema de representación, ya que no me parece interesante. De cualquier modo, en una futura lección le prestaremos más atención a este sistema, simplemente para que lo conozcais mejor. Eso os lo dejo a vuestra elección.