jueves, 10 de enero de 2008

Ensamblador (Entrega 1)

En el principio, era el cable

Las computadoras primitivas se programaban mediante el cambio de las conexiones (cables) en un panel dispuesto a tal efecto. Este cambio de conexiones modificaba la lógica del sistema y permitía “resolver” problemas de baja complejidad en forma repetida. Como podrán notar, este tipo de programación se realizaba mediante el hardware y era un proceso bastante complejo, lento e ineficiente que requería por parte del “programador” un conocimiento pleno de los circuitos de la computadora. Crear o modificar un programa constituían emprendimientos mayores por el tiempo y la dedicación de los “programadores”.

El primer salto cualitativo se produjo con la evolución de los dispositivos de almacenamiento, en principio las memorias de núcleo y luego, con la miniaturización, los circuitos integrados o “chips”. En forma paralela, muchos usuarios (oficinas gubernamentales, universidades, institutos de investigación, etcétera) percibieron la necesidad de resolver un amplio conjunto de problemas en forma relativamente rápida. Estas dos fuerzas dieron nacimiento al lenguaje ensamblador que se caracteriza por mantener una estrecha relación con el lenguaje de la máquina

El conjunto de códigos de instrucción del lenguaje de máquina forma parte de la arquitectura de la unidad central de proceso y consiste de un conjunto de valores binarios que señalan operaciones específicas. Estas instrucciones son reconocidas por el procesador por el código binario (o exadecimal) correspondiente, por ejemplo la instrucción B4 significa cargar la parte alta del registro AX (o sea AH) con el valor que sigue. La particularidad del lenguaje ensamblador consiste en tener una instrucción con un nombre simbólico fácil de recordar, para cada instrucción o conjunto de instrucciones de máquina. Las instrucciones del lenguaje ensamblador se denominan mnemotécnicas debido a que pueden memorizarse con facilidad.

La CPU (PC 8088, etcétera)


Fig. 1 Arquitectura simplificada de la CPU

Recorrido de los registros

La mejor manera de entender la estructura de la unidad central de proceso o CPU, consiste en meterse en el interior y explorar sus registros y su unidad de aritmética y lógica o ALU. Y la forma de meterse y espiar estas cosas está al alcance de cualquier usuario de PC, por medio del programa Debug.



Fig. 2 Esquema del proceso de ensamble del lenguaje simbólico al código de máquina


Las primeras prácticas estarán dirigidas a recorrer todos los registros (8) disponibles en la CPU y, para facilitar las cosas, realizaremos tres ejemplos completos que les servirán de guía, con el empleo del programa debug.


En estos ejemplos se mostrarán tres modalidades de la instrucción MOV, la primera consistirá en la carga de un registro con un valor constante, luego veremos la carga de un registro desde una dirección de memoria (previamente inicializada) y, finalmente mostraremos la carga de un registro desde otro registro.

A las cosas como decía Ortega y Gasset

Pasemos directamente a un simple ejemplo para comprender de qué estamos hablando.

Ejemplo 1: Mover un valor constante a un registro.

Para ejecutar Debug, hay que iniciar una sesión DOS. Esto se consigue por medio del menú Inicio:

Inicio/Ejecutar/


Fig. 3 Cuadro de diálogo "Ejecutar" (command)


Una vez en DOS (no se alarmen si aparece “parado” en otra carpeta que no sea C:\WIND)

El programa debug muestra un guión –

Detrás de ese guión deben escribir los comandos (en este caso son cuatro: a, g 100, p y q)

a le dice a debug que ensamble las instrucciones que siguen

g 100 le dice que “vaya” a la posición 100 (que es donde comienza el programa)

p le dice que “avance” un paso

q le dice que “salga” (quit)

Sesión completa de Debug

C:\WIND>debug
-a
3902:0100 MOV AX,123
3902:0103
-g 100

AX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0100 NV UP EI PL NZ NA PO NC
3902:0100 B82301 MOV AX,0123
-p

AX=0123BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0103 NV UP EI PL NZ NA PO NC
3902:0103 3028 XOR [BX+SI],CH
-q

Explicación

Al ejecutar DEBUG, se presenta un guión (-) que permite ingresar los comandos para realizar diversas tareas. El primer comando que utilizamos es A (ensamblar) que nos presenta la dirección actual (3902:0100). Nosotros ingresamos la instrucción MOV AX,123 que carga el registro AX con la constante 123 y oprimimos INTRO. Luego, debug presenta la próxima dirección disponible (0103), en esta dirección, no ingresamos ninguna instrucción, sino que oprimimos INTRO para retornar al guión de debug.

Hasta aquí, tenemos nuestra instrucción lista en la memoria para ser ejecutada, por lo tanto, empleamos el comando G (ir) que permite ejecutar el programa, dando comienzo en la dirección que se indica a continuación. El programa consiste de una línea, simplemente le indicaremos a debug que vaya a la dirección 100 y que se detenga allí (g 100). Debug, entonces, se detiene en 100 y aún no ha ejecutado la intrucción MOV. Sin embargo, debug nos muestra el estado de los registros en las dos primeras líneas, mientras que la tercer línea muestra la dirección actual seguido por el código de máquina generado y la intrucción en lenguaje ensamblador:

AX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0100 NV UP EI PL NZ NA PO NC
3902:0100 B82301 MOV AX,0123

Como podemos observar, el registro AX contiene el valor 0, es decir, aún no está cargado con la constante 123. Para ejecutar la línea 100 utilizamos el comando P (continuar) que pasa a la siguiente dirección.

AX=0123BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0103 NV UP EI PL NZ NA PO NC
3902:0103 3028 XOR [BX+SI],CH

Observe la tercer línea que muestra la dirección actual (103), ignore la instrucción XOR ya que es lo que se denomina “basura” (garbage en inglés) que consiste en contenidos arbitrarios de esa posición de memoria. Observe ahora el estado del registro AX y notará el valor 123, es decir que nuestra instrucción fué ejecutada exitosamente.

¡Listo!

Realice el ejemplo y pruebe con otros valores y otros registros, tales como BX, CX, DX, etcétera.


Hasta la próxima entrega,

Sergio Otaño

0 comentarios: