Programación en Lenguaje Ensamblador

-El Verdadero Lenguaje de las Máquinas-

+++ Positivo y Negativo – – –

–Números Binarios Con y Sin Signo–

Hasta ahora, la entrada de este blog que ha sido mas leida es la de ¿Cuantos bits tiene un Byte?. En esa entrada se deja en claro lo que es un byte. Una celda de 8 bits que puede almacenar cualquier número entero entre 0 y 255.

Sin embargo, cada uno de estos valores puede ser interpretado de 2 maneras diferentes dependiendo del contexto en que se trabaje.

Números sin signo.- Estos son los de siempre. Cuenta de cero a 255.

Números con signo.- Con los mismos 8 bits de un byte, podemos representar los números desde el -128 al 127. Si se fijan, estos son 256 valores diferentes.

Todos estos conceptos son suficientemente complejos para que se les dedique un examen completo en una carrera de Ingeniería en Computación. Sin embargo, en este dibujo que recuerda a un Yin-Yang chino pueden verse la mayoría de los conceptos que tienen que ver con esto de los números enteros con y sin signo:


binyang

Este círculo se lee exactamente igual que un reloj analógico. (De manecillas) Se parte del punto mas alto donde está el valor 0 y se recorre toda la circunferencia hasta llegar a donde empezamos. De hecho, al igual que el reloj, la cuenta que lleva un byte vuelve a comenzar al dar una vuelta completa. Este fenómeno se llama WRAP-AROUND y es la base de la aritmética de enteros signados, (que no es lo mismo que santiguados). Este fenómeno era muy común en los juegos de principios de los años 80 como Asteroids, en donde si uno salía por un lado de la pantalla, magicamente aparecía por el lado de la pantalla opuesto.

Sin embargo, las similitudes con el reloj convencional terminan aquí. Pues esta rueda puede moverse en sentido opuesto a como lo hacen las manecillas. Pues del mismo modo que si tenemos 255 y le sumamos uno el contador se reinicia en cero, si tenemos cero y restamos uno, el contador marcará 255. Esto tiene perfecto sentido en los números sin signo, representados aquí en color gris tanto en decimal como en Hexadecimal. Entonces, para dar una vuelta completa al circulo, hay que dar 256 pasos. Pero eso es solo porque esta representación es de 1 byte.

Números con signo.- Cuando usamos signo, la mitad de los números son positivos y la mitad negativos. Aunque hay 2 casos especiales:

Cero Positivo.- Aunque matemáticamente el cero no es ni positivo ni negativo, y puede dividirse entre cualquier número. Dentro de un CPU un cero se considera positivo y par. Pero esto es válido solo para las representaciones de números enteros, pues en Punto Flotante pueden representarse ceros positivos (porque tienen SIDA) y negativos para su uso en cálculo infinitesimal. El cero siempre tiene todos los bits puestos en cero sin importar si se trata de un registro de 8, 16, 32, 64, etc. En el diagrama, el cero se encuentra en la parte mas alta del círculo del lado positivo (azul).

El Gran Negativo.- El -128 es el número negativo con mayor valor absoluto que puede representarse en 8 bits. Para compensar el hecho de que los negativos no tienen cero, los positivos no tienen el +128. El número negativo con mayor valor absoluto puede ser:

-128 en 8 bits,

-32768 en 16 bits,

-2,147,483,648 en 32 bits

y -9,223,372,036,854,775,808 en 64 bits.

En realidad no importa el ancho del registro, el Gran Negativo siempre se representa con todos los bits en cero excepto el bit mas significativo. En el diagrama, el Gran Negativo se encuentra en la parte mas baja del círculo, del lado negativo (rojo).

Lo interesante es que la computadora no sabe ni le importa si el valor en el registro tiene signo o no. Si en la parte baja del acumulador hay un A0h el CPU no sabe si se trata de un 160 sin signo o un -96 con signo. Mas adelante veremos como el CPU evalúa un resultado con el registro EFLAGS. Los números entre el 0 y el 127 con signo se manejan igual a los que no tienen signo.

Bit Signo.- Es el bit mas alto del registro. Si está en uno el valor es negativo y se está en cero es positivo. Podría decirse que ese es el ‘bit del mal’. Pero ojo, si queremos convertir un número positivo a negativo, o viceversa, hace falta mucho mas que solo cambiar el valor de este bit. Hay que ‘negarlo’ con la instrucción NEG.

NOT.- Esta operación es muy simple, enciende todos los bits apagados y apaga todos los bits entendidos. En el círculo, esta operación funciona como un espejo,pues solo hay que trazar una linea horizontal desde el valor que queremos hacerle el NOT hasta el otro lado de la rueda. Pero Ojo, los números no son simétricos. La suma de cualquier número mas su valor NOT es igual a todos los bits activos, en este caso -1 con signo y 255 con signo.

NEG.- La instrucción NEG cambia el signo de un valor entero. Si es positivo lo hace negativo y el negativo a positivo. Para que no se les olvide, el NEG es como una opreración de cambio de sexo (u operación jarocha como diríamos en México).Primero hace un NOT y luego suma un uno. Esto se ve en el círculo donde están las flechas azul y roja y la palabra NEG. Se traza una linea hasta el otro lado de la rueda y se avanza una unidad para cambiar el signo. Pero hay 2 excepciones: El Cero y en Gran Negativo. Si le aplicamos el NEG a cualquiera de estos 2 valores no sucederá nada. Tan solo se activará la bandera CARRY en el registro EFLAGS.


rango entero

Por último, hay que dejar claro que para el CPU hay una gran diferencia entre el hecho de que un número sea mayor o menor que otro y que esté por encima o por debajo de otro. En este otro dibujo vemos el mismo círculo de la primera ilustración en forma ‘desenrrollada’ y podemos ver lo complicado que resulta representar números con signo de manera no circular.

El concepto de MAYOR y MENOR solo aplica para los números con signo. Mientras que ARRIBA y ABAJO es solo para los que no tienen signo. Por ejemplo, el -1 es menos que 100 pero a la vez -1 está por encima del 100 porque -1 es 0FFh mientras 100 es 64h. Esto tiene una ventaja, si queremos ver si un resultado está entre 0 y 50, en lugar de hacer 2 comparaciones (resultado < 0 y resultado > 50) hacemos solo una, donde vemos si el resultado está por debajo del 50. Pero esto ya es asunto del registro EFLAGS.

De acuerdo, ya me extendí demasiado. Para acabar solo queda decir que no hay que confundir el Carry con el Overflow. Supongo que ya debería de hablar de como toma decisiones la computadora. Pero por ahora a insultar:

Hace unas horas eché un vistazo al circo de pulgas. Es increible como llevan casi un mes tratando de unir todos los archivos de sus sprites lameados con alguna aplicación. Al parecer alguien se queja de que la única aplicación que encontró para hacer esto solo los ordena de modo vertical. ¡Estos lamers no saben que en esa disposición es mas sencillo su almacenamiento y recuperación en la memoria! Quieren que el programa acomode los sprites en una matriz bidimensional donde todos los sprites quedan en celdas del mismo tamaño. De hecho en el foro viene una secuencia de animación de un Ha-Do-Ken. (Suerte que esta vez no le dijeron ‘abuken’) y cada cuadro de animación es por lo menos 9 veces mas grande que el sprite que contiene. Lo que significa que, como no creo que sepan nada de compresión en tiempo real, van a gastar 9 veces mas memoria solo en esa animación. En otro thread, al parecer están planeando una orgía. Pero eso ya no tiene nada que ver con la programación. Bueno, ahí le dejo porque tengo que planear nuevas bromas crueles para este blog.

abril 16, 2009 Posted by | Uncategorized | , , , , , , , , | 21 comentarios

Prog, Hex and Rock’n’Roll

–Todo Sobre el Sistema Hexadecimal–

Los sistemas numéricos son un mal necesario en el mundo de la computación, de hecho, el sistema decimal es sencillo de manejar y es el que mejor conocemos, pero para la computadora no significa nada. El binario es su idioma nativo y es con el que trabaja. Pero es demasiado tardado y confuso usarlo. La pregunta de los 65,536 sería ¿Habrá un sistema numérico que tenga las ventajas de ambos? La respuesta es si, se llama sistema hexadecimal y será el tema de esta nota.

Antes de continuar, se que este blog tiene 2 tipos principales de lectores (sin contar a los que vienen por la botana y a ligar) la primera clase son los lamercitos de escuela que les dejan de tarea copiar e imprimir páginas de internet como esta y la otra, los menos, son los principiantes que realmente les interesa el Ensamblador. En realidad, sería raro que un programador de cierto nivel buscara información en español. Mas bien teclean “Assembly Language” en el Google. Así que tomaré esto con calma.

Los ‘números’ de todos los días son 10, y van del 0 al 9. Los hexadecimales son 16. Se usan las letras de la A a la F para representar del 10 al 15. Vean la siguiente tabla:

DECIMAL   HEXADECIMAL       BINARIO

      0             0          0000

      1             1          0001

      2             2          0010

      3             3          0011

      4             4          0100

      5             5          0101

      6             6          0110

      7             7          0111

      8             8          1000

      9             9          1001

     10             A          1010

     11             B          1011

     12             C          1100

     13             D          1101

     14             E          1110

     15             F          1111

Esta tabla es importante, así que les recomiendo que la impriman y la peguen en la pared junto al programa PEDEMO.EXE del Fasm. Ahora veamos como hacer las conversiones rápidas.


cuadro gris

El primer paso para convertir un número a sistema Hexadecimal es convertirlo a binario. Moverse entre decimal y hexadecimal es mentalmente muy tardado y requiere mucha experiencia. Para el caso de las celdas de un BYTE, primero hay que escribir los 8 bits. Esa ristra de ceros y unos se parte en 2 mitades de 4 bits cada una y a continuación se convierte cada una de estas viboritas(llamadas NIBBLES en los libros mas antiguos) equivale exactamente a una cifra Hexadecimal. El dibujo que acompaña a esta entrada describe de manera clara como se convierte una celda de 8 bits a hexadecimal. Pero antes de que se harten y se vayan a trabajar en Visual Basic (las palabras ‘programar y ‘Visual Basic’ no pueden ir en la misma frase) veamos algunas de las virtudes de los números hexadecimales:

*La conversión entre Hexadecimal y Binario se puede hacer mentalmente de manera muy rápida.

*Con solo ver un número hexadecimal podemos saber cuantos bits se necesitan para representarlo.

*Podemos saber si un entero es positivo o negativo con solo ver su primer cifra hexadecimal.

*En cuanto a las posiciones de memoria. Podemos saber si están alineadas adecuadamente por la cantidad de ceros al final.

*No importa que número representemos, mientras solo usemos 2 cifras no sobrepasaremos el límite de un byte. Lo mismo aplica para las 4 cifras en un word(l6 bits) y 8 cifras para el DWORD (32 bits)

*El máximo número representable por un byte es ‘FF’, de un word es ‘FFFF’ y de un dword es ‘FFFFFFFF’. En el caso de la aritmética entera, estos números también significan menos uno.

*Si no aprenden Hexadecimal van a cagar chayotes cuando quieran programar de verdad. Así que pónganse a practicar o si no vayan buscándose algún trabajo mas sencillo como hacer querys.

Existe otro sistema llamado Octal, que es lo mismo pero cada cifra es representada por 3 bits. No se usa mucho, solo lo he visto para representar OpCodes en Intel y algunas cosas con los discos duros. Y si ya se aburrieron esperen a ver lo que sigue, será una auténtica ‘bienvenida al Mundo Real’.

>>>>Pasa al siguiente nivel>>>>

***Esta nota pertenece a “La Saga del Completo Principiante”*** Da click en este enlace para pasar a la siguiente entrada de esta serie.

diciembre 31, 2008 Posted by | Uncategorized | , , , , , | 14 comentarios