=======================================================
Introduccin a la programacin en lenguaje ensamblador
para procesadores Intel serie x86 y compatibles (I)
=======================================================

Por nmt
numit_or@cantv.net

===============================
CONSIDERACIONES PRELIMINARES I
===============================

--------------------------------------------------------
  CONTENIDO

 - Consideraciones Preliminares
	 Bajo Nivel - Alto Nivel
	 Objetos

 - Entonacin

 - Unas palabras sobre las macros

 - Consideraciones necesarias sobre el hardware


-----------------------------
Consideraciones Preliminares
-----------------------------

Bajo Nivel - Alto Nivel
-----------------------
El llamado lenguaje ensamblador  no es ms que un  conjunto de  etiquetas  para
cada  una  de  las  instrucciones  que  constituyen  el cdigo  de  operacin a
travs del cual programamos un microprocesador.

El procesador trabaja con un cdigo binario,  constituido por  palabras  hechas
con  combinaciones  de  dos  estados  o  valores:  1  y  0.  Debido a  la  gran 
dificultad que supone escribir programas con estos elementos,  se asign a cada 
instruccin una etiqueta, que sirviera de mnemotcnico, y se dise un programa 
que  tradujera  cada  etiqueta  a  cdigo  binario.  A  este programa se  llam 
<<ensamblador>>.

Ahora  el programador slo tena que escribir  una secuencia mnemotcnicos  que
representaban  las  instrucciones  binarias que deba seguir un microprocesador
para realizar sus tareas. Luego pasaba el cdigo escrito por el ensamblador que 
habra de generar un programa en cdigo  binario que la mquina poda seguir  a 
cabalidad.

An as, la programacin en ensamblador sigue siendo una tarea ardua.  Acciones
aparentemente  simples   requieren  que   el  microprocesador   ejecute  muchas 
instrucciones.  Para  facilitar  la  labor,  se  implementaron  mecanismos para 
empaquetar varias instrucciones en  una sola:  las  macros.  Se reservaban  las 
macros  especialmente  para  esas  secuencias  de instrucciones que se repetan 
mucho.  Una  macro  no hace sino decirle  al  ensamblador  que  despliegue  una 
secuencia  muy especfica de instrucciones en  los  puntos  donde  aparece  una 
cierta instruccin simple.

Con las macros ya se comienza a dar un aspecto <<ms humano>> al cdigo escrito 
en ensamblador.  El  problema  de las macros es que siempre despliegan el mismo 
cdigo,  incrementando  intilmente  el  tamao  del  programa  ya ensamblado y 
haciendo ms lento su tiempo de ejecucin.

Los  llamados  lenguajes de alto nivel son  precisamente un conjunto de macros: 
por  eso tienden a generar programas ms lentos y grandes que los generados por 
un programa escrito en esamblador.

Los lenguajes de alto nivel, como PASCAL o BASIC, generan cdigo en ensamblador 
que nunca sabemos que hace ni cmo es.  Parte  de  ese  cdigo  tendramos  que 
escribirlo  si los compiladores de los lenguajes de alto nivel no lo generaran. 
El problema es que casi siempre generan cdigo de ms sobre el cual no  tenemos 
estricto control.

Antes de optar por aprender ensamblador,  hay que tener en cuenta que se  trata 
de un lengaje exigente y poco agradable. Su eleccin y  supervivencia reposa en 
que  gracias a l se obtienen programas mas  pequeos y rpidos,  as  como  un 
control total sobre el microprocesador y los dispositivos de un sistema.


Objetos
-------
Mi  experiencia  en  el  trabajo  con lenguaje ensamblador me ha demostrado que 
siempre  hay  que  tener una imagen general del proyecto,  con cierto nivel  de 
abstraccin respecto al funcionamiento del  microprocesador.  Hay  que  atender 
especialmente a las relaciones que deben haber entre  las partes del  proyecto: 
todo proyecto conviene ser dividido en partes u objetos de diversos tipos.  Por 
objeto entiendo aqu un bloque definido del programa.  Cada bloque del programa
puede  incluir  datos y/o cdigo:  la materia  de trabajo (datos) y lo que debe 
hacerse con esa materia (cdigo).

La  diferencia entre cdigo  (o  conjunto de instrucciones del programa)  y los 
datos (valores con los que trabaja un programa)  ofrece un primer criterio para 
ordenar tipos de objetos.  De hecho, los programas que corren en DOS se dividen 
en segmentos,  unos  reservados para los datos y otros para las instrucciones o 
cdigo.

Puede  verse que un objeto no es aqu ms que *un bloque de memoria* especfico 
que agrupa cosas de un tipo definido.

Pero hay tipos de tipos.  As  que entre los objetos  del tipo dato hay tambin 
tipos de datos.  En  ensamblador los tipos de datos  suelen  definirse  por  su
tamao.

El  tamao  de  los  datos  se  mide  en  <<bytes>> == 8 bits. Los bits son los 
elementos mnimos de informacin binaria.  Un bit puede ser un 1 o un 0.  Con 8 
bits formamos una unidad mayor llamada byte. Con dos bytes formamos otra unidad 
de 16 bits que llamamos palabra (word); con dos palabras formamos  un  tipo  de 
datos LONG (largo) de 32 bits que llamamos palabra doble (double word), y as.

Podemos incluso formar datos complejos formados por varios tipos de subdatos. A 
estos nuevos tipos de datos los llamamos estructuras. Si estas unidades mayores
constan de objetos del mismo tipo, entonces tenemos un array o vector.

A  grosso modo tambin podemos subdividir el cdigo de un programa en  lenguaje
ensamblador  en  subtipos de cdigo.  A  cada  grupo  de cdigo destinado a una 
operacin  especfica  se  le  llama procedimiento.  Generalmente tendremos que 
escribir  un  cdigo  para  la  inicializacin  del programa (constructor) y un 
cdigo para su destruccin (destructor). Otro cdigo debe encargarse de atender 
los requerimientos que hace el usuario al programa (interface).

Cmo puede observarse, un programa consta de objetos ntimamente relacionados y 
con funciones muy especficas.

Para  ilustrar  estos primeros conceptos revisemos un programa sencillo escrito 
en lenguaje ensamblador.


-----------
Entonacin
-----------
Antes de escribir un programa, debemos crear un entorno de trabajo.

Primero debemos disponer de las herramientas necesarias. Para nuestras primeras 
tareas basta:

         Un ensamblador (TASM o NASM)
         Un enlazador (TLINK o ALINK)
         Un editor de texto (notepad.exe, edit.com, vi.exe)

Con estas herramientas podemos escribir nuestro primer lenguaje en ensamblador, 
en este caso para DOS.

Baja este fichero:
http://mipagina.cantv.net/numetorl869/TASM2.zip

Descomprmelo y ejecuta INSTALL.BAT. Obtendrs un directorio nuevo:

        C:\TASM

con un subdirectorio

        C:\TASM\BIN

donde estarn las herramientas necesarias.

Como editor puedes usar EDIT de DOS o, si corres en Windows, el notepad.

Antes que nada, escribamos el programa.

Primero  hay  que  especificar el modelo de memoria,  el cual determina cuntos 
segmentos voy a usar. Vamos a usar uno para los datos y uno para el cdigo. As 
que  elegimos  SMALL.  Para  sealar  el  modelo de memoria usamos la directiva 
".MODEL", seguida por el modelo elegido:

        .MODEL SMALL

Otros modelos de memoria son:

        TINY    reservado para generar ejecutables .COM: 1 segmento
                para datos y cdigo, todo en un nico segmento.
        FLAT    1 segmento de datos, 1 seg. de cdigo.
        MEDIUM  Varios segmentos de datos, 1 seg. de cdigo.
        COMPACT 1 seg. de datos, varios de cdigo.
        LARGE   Varios segs. de datos, varios de cdigo.        

Luego  especificamos el conjunto de instrucciones. Generalmente se elige el del 
Intel 80386:

        .386

indicar.  Por ejemplo, para instrucciones del 586, escribiremos ".586". Tambin 
se  pueden  incluir instrucciones de los procesadores MMX, que sern entendidas 
por  ensambladores  actualizados,   pero  que  slo  corrern  en  procesadores 
compatibles con MMX: ".MMX".  TASM  requiere el uso de macros  especiales  para 
ensamblar instucciones el MMX; MASM no.

Ahora definimos los segmentos para nuestros objetos. No slo bastan el segmento 
de  datos y el de cdigo.  Se necesita un segmento ms para la pila (stack) del 
programa, que consiste en  un  rea de memoria que se reserva para facilitar el 
manejo de los datos.  La  definicin  de los segmentos se realiza mediante unas 
directivas especiales:

        .stack

        .data

        .code

Cada  una  de  estas directivas define un segmento para la pila, los datos y el 
cdigo, respectivamente.

Para definir el tamao de la pila escribimos algo como:

     .stack 64

que reserva un segmento de 64 bytes para la pila del programa.

En el segmento .data escribimos nuestros datos. En este caso la declaracin de 
una cadena de caracteres:

        .data
string  db      "Hola gente", "$"

La palabra "string" es el nombre del dato,  el trmino "DB" es el tipo de dato 
( tamao de un byte), y luego, entre comillas una cadena de caracteres seguido 
por el nmero 36 despus de una coma.  El  nmero  36  es  el cdigo ascii del 
carcter "$" que usa para indicar el final de  la  cadena.  Debido  a  ciertas 
inconsistencias, el ensamblador puede no interpretar el caracter "$" como tal; 
as que mejor es indicar el cdigo ascii correspondiente.  Lo  mismo vale para
ciertos caracteres como , , los que tienen acentos, etc.

Finalmente escribimos el cdigo para desplegar esta cadena en el monitor:

        .code
  main  proc    far
  _init:
        mov     ax, @data 
        mov     ds, ax
  _display:
        lea     dx, string
        mov     ah, 9
        int     33 
  _pause:
        mov     ah, 16
        int     22
  _exit:
        mov	ah, 76
	int	33
  main  endp

El objetivo del programa es simplemente la entonacin de la  mquina.  As  que 
dejo para luego su anlisis. De todos modos, he agregado unos marcadores,  unos 
nombres o etiquetas seguidos por dos puntos. Esos marcadores indican cada  paso 
de nuestro programa.  Aunque  no  sepamos lenguaje ensamblador,  esas etiquetas 
nos  dicen  que  ocurre  cuando  corre  nuestro programa: le programa se inicia 
(init), despliega una cadena de  caracteres (_display), se detiene la ejecucin 
del programa hasta que se pulsa una tecla (_pause), se regresa a DOS (_exit).

Ahora ponemos todo junto :

; --------------------------------------------------------
  TITLE PRIMER.ASM: Primer programa escrito en ensamblador
; --------------------------------------------------------
        .MODEL SMALL
; --------------------------------------------------------
        .stack 64
; --------------------------------------------------------
        .data
  cadena        db      'Hola gente!', '$'
; --------------------------------------------------------
        .code
  main  proc    far
  _init:
        mov     ax, @data 
        mov     ds, ax
  _display:
        lea     dx, cadena
        mov     ah, 9
        int     33 
  _pause:
        mov     ah, 16
        int     22
  _exit:
        mov	ah, 76
	int	33
  main  endp
; --------------------------------------------------------
  end   main
; --------------------------------------------------------

Copiamos el dicho programa y lo guardamos como PRIMER.ASM.

Para  obtener un ejecutable a partir de PRIMER.ASM,  tenemos  que ensamblarlo y 
enlazar  sus  segmentos.  El  ensamblado  se  hace  usando  un programa llamado 
ensamblador, que lee el programa escrito o cdigo fuente,  traduce su contenido 
a cdigo mquina y lo guarda en un archivo .OBJ. Para hacer funcional el cdigo 
de un archivo .OBJ,  debe ser adaptado al  formato  de los archivos ejecutables 
del sistema operativo; esto lo hace el enlazador que,  en este caso,  producir 
un archivo ejecutable .EXE, acomodando debidamente los segmentos del programa.

As que slo tenemos que ejecutar desde la cnsola:

        tasm primer
        tlink primer

La primera lnea ensambla primer.asm y genera primer.obj.  La  siguiente  lnea 
enlaza primer.obj y crea nuestro ejecutable: primer.exe.

Por supuesto,  el  directorio  donde se encuentran tasm.exe y tlink.exe debera
estar includo en la variable PATH.  Para  ello,  ejecutamos la siguiente lnea 
desde la cnsola, antes de ejecutar las rdenes de arriba:

	PATH C:\TASM\BIN;%PATH%

Para  facilitar  el  proceso  de  ensamblado,   podemos  crear  un  archivo  de 
procesamiento por lotes que podemos llamar  MAKE.BAT  que  contenga  estas  dos 
lneas. Yo he escrito el siguiente:

----------------------------------------

        @echo off
        CALL C:\TASM\BIN\TAENV
        SET NAME=PRIMER
        IF EXIST *.OBJ GOTO LNK         
        @echo on
        TASM %NAME%.ASM
        IF ERRORLEVEL GOTO ERR1
        cls
        :LNK
        TLINK %NAME%.OBJ
        IF ERRORLEVEL GOTO ERR2
        IF EXIST *.OBJ DEL *.OBJ
        cls
        exit
        :ERR1
        @echo.
        Error al ensamblar!
        PAUSE
        cls
        exit
        :ERR2
        @echo.
        Error al enlazar!
        PAUSE
        cls
        exit

-- Jaja, es ms largo que nuestro programa en ensamblador !) --

Es  el  que  aconsejo,  ya que puede ser usado para otros proyectos;  se  puede 
cambiar la asignacin:

SET NAME=proyecto

de  manera  que  "proyecto"  designe  el  nombre del fichero .ASM que deseamos 
ensamblar.

MAKE.BAT  ejecuta  al  comienzo  el  archivo  "TAENV.BAT",  en  el  directorio
"C:\TASM\BIN\",   que  establece el entorno apropiado, colocando el directorio
"C:\TASM\BIN\", donde se encuentran los ejecutables de TASM,  en  la  variable 
PATH del sistema.  Adems,  al ejecutarse este .BAT, se indicar en cnsola si 
ha habido algn problema en tiempo de compilacin.

Debemos  ponerlo en el mismo directorio que  elegimos  para  PRIMER.ASM.  Slo 
tenemos que ejecutarlo y se ha de producir  un  archivo:  PRIMER.EXE,  que  al 
ejecutarlo debe desplegar en la cnsola "Hola Gente!".  Luego  pulsamos alguna 
tecla y debemos regresar a DOS.

Nota el tamao del archivo ejecutable generado:  544 bytes,  y puede reducirse 
an ms.  Es  la  magia  de  escribir  en lenguaje ensamblador. Podra ser ms 
pequeo, pero ahora slo nos interesa probar el entorno.



-------------------------------
Unas palabras sobre las macros
-------------------------------
Como  mencion  en  mis  palabras  preliminares,  la complejidad  del lenguaje 
ensamblador,  el  hecho  de  que una accin simple de un algoritmo necesite la 
ejecucin de varias instrucciones del procesador,  que  una  secuencia  de  un 
programa  ensamblador  con  mucha  dificultad  refleje  las  ideas que quieren 
comunicarse  al  sistema,  estas  circunstancias  han  motivado la creacin de 
sistemas alternativos dentro del mismo lenguaje.

Como puede observarse,  desde  hace  mucho los ensambladores son dotados de un
preprocesador,  de la capacidad,  por ejemplo, de dar soporte a la creacin de 
macros.  Las  macros  no  slo aligeran trabajo,  sino  que  tambin  permiten 
"encerrar" o "encapsular" una serie de instrucciones,  que generalmente es muy
reiterativa, dentro de un trmino.

TASM  y  MASM  suministran soporte para macros.  La  sintaxis igual para ambos
ensambladores:

etiqueta        MACRO parmetro1, parmetro2, ..., parmetroN
                ...
                ...
                instrucciones
                ...
                ...
                ENDM

Cada vez que el ensamblador encuentre la "etiqueta" de una  macro, desplegar 
automticamente las instrucciones que contiene.

Para  que se vea la ventaja de las macros, apliqumoslas en nuestro programa. 
Tomemos  los  marcadores  que  empleamos  y hagamos de ellos las etiquetas de 
nuestras macros:

  _init         MACRO
                mov     ax, @data 
                mov     ds, ax
                ENDM


  _display      MACRO   a
                lea     dx, a
                mov     ah, 9
                int     33
                ENDM


  _pause        MACRO
                mov     ah, 16
                int     22
                ENDM


  _exit         MACRO
                mov	ah, 76
		int	33
                ENDM

Tenemos  as  un  conjunto de cuatro macros que deben colocarse al comienzo del 
fichero  con el cdigo  fuente .ASM,  despus  de la indicacin del  modelo  de 
memoria.

Generalmente  lo  que  se hace es colocarlas en un fichero aparte con extensin 
.MAC o .INC. Podra ser "macros.inc". Luego se agrega al comienzo  del  fichero 
con el cdigo fuente .ASM la siguiente instruccin de preprocesador:

                INCLUDE macros.inc

Lo que hace esta instruccin es "incluir" el  contenido  en  macros.inc  en  el 
punto preciso donde est la instruccin.

Es ms, podramos hasta poner en nuestro fichero macros.inc las primeras lneas 
de nuestro programa original, si vamos a escribir muchos programas con el mismo 
encabezado; as que agregamos las siguientes lneas en macros.inc,  despus  de 
nuestra lista de macros:

        .MODEL SMALL
        .stack 64
        .data


Si aplicamos estas posibilidades a nuestro proyecto,  nuestro  cdigo  quedara 
as:


; --------------------------------------------------------
  TITLE PRIMER.ASM: Primer programa escrito en ensamblador
; --------------------------------------------------------
        INCLUDE macros.inc
; --------------------------------------------------------
  string        db      'Hola gente!', 36
; --------------------------------------------------------
        .code
  main  proc    far
        _init
        _display string
        _pause
        _exit
  main  endp
; --------------------------------------------------------
  end   main
; --------------------------------------------------------

Como puede notarse,  se  escriben menos lneas y el cdigo se hace ms legible, 
reflejando con ms cercana el algoritmo que deseamos compute nuestro sistema.


---------------------------------------------
Consideraciones necesarias sobre el hardware
---------------------------------------------
Antes  de  entrar  en  el  calor  de  la  batalla,  son indispensables algunas 
consideraciones sobre la arquitectura del hardware de la PCs. 

Haba  quedado  pendiente  explicar  qu  es  un registro y cuntos tienen los 
procesadores  ix86.  Tambin  ha  quedado pendiente qu es una interrupcin. A 
continuacin intentar explicar estas cuestiones.


(TO BE CONTINUED...)

