         INTRODUCCION AL ASM: USO DE LOS PROGRAMAS ENSAMBLADORES (II)
         ============================================================

   Continuamos en este octavo captulo del curso la explicacin del HELLO.ASM
en el punto donde la dejamos al final del anterior captulo.

   El ltimo segmento del programa es el segmento de cdigo, al que le hemos
dado el nombre 'CODIGO'. La primera lnea de este segmento es un ASSUME, cuya
funcin vamos a ver detalladamente.

   Cuando vimos los distintos modos de direccionamiento, vimos que cada uno
usaba un registro segmento por defecto (por cierto, uno de los registros de
segmento estaba equivocado: el modo [BP+xx] usa el segmento SS por defecto, y
no el DS como apareca). Cuando queremos que una instruccin que opera por
defecto con un segmento opere con otro, es necesario anteponer al operando que
referencia a memoria el nombre del segmento seguido de dos puntos. Por ejemplo,
veamos la siguiente instruccin, que accede al segmento apuntado por DS:

		mov ax,[0]

   Si queremos que cargue la primera palabra del segmento apuntado por CS:

		mov ax,cs:[0]

   A nivel de cdigo de mquina, lo que se hace es prefijar la instruccin an-
terior con un byte (existen cuatro posibles valores, uno para cada segmento)
que especifica que no se debe usar el segmento por defecto. A este prefijo se
le suele denominar 'segment override'.

   Cuando en un listado en lenguaje ensamblador se genera un acceso a memoria,
el ensamblador es capaz de meter automticamente 'segment override's donde sea
necesario (adems de permitirnos especificarlos a nosotros). Para ello, hay que
decirle al ensamblador a cual de los segmentos que hemos definido en el listado
est apuntando cada uno de los registros de segmento. As, cuando generamos una
referencia a una etiqueta, comprueba en qu segmento ha sido definida y busca
cul de los registros de segmento apunta a se segmento. As, puede decidir si
es necesario generar un 'segment override', y cul de ellos es necesario. la
directiva 'ASSUME' dice al ensamblador a qu segmento apunta cada registro de
segmento, como vemos en HELLO.ASM. De todas maneras, somos nosotros los encar-
gados de hacer que, efectivamente, los registros de segmento apunten a los seg-
mentos especificados.

   En caso de que el ensamblador encuentre un acceso a una etiqueta definida en
un segmento no mencionado en el ASSUME, se quejar con un error del tipo
'unreachable data' ('datos inaccesibles').

   Si un segmento no va a estar apuntando a ninguno de los segmentos definidos
en el listado (por ejemplo, si apunta a la memoria de vdeo), se puede aadir
un ASSUME con nombre de segmento 'NOTHING', de manera que el ensamblador no
asuma que el registro de segmento en cuestin permite acceder a ninguna varia-
ble conocida.  Al principio del proceso de ensamblado, el ensamblador est como
si hubiera ledo una lnea as:

	ASSUME CS:NOTHING, DS:NOTHING, ES:NOTHING, SS:NOTHING

   Es importante comprender el funcionamiento de la directiva ASSUME, ya que
puede causar confusiones en algunos casos.

   Dentro de un segmento de cdigo, las instrucciones incluidas pueden estar
agrupadas en bloques lgicos, llamados 'procedimientos'. Estos funcionan a modo
de las funciones de C o los procedimientos y funciones de Pascal. Aunque las
ltimas versiones de los ensambladores permiten dar listas de argumentos, va-
riables locales, etc... (generando el cdigo oportuno para manejarlos), no en-
traremos en ello. Para nosotros no ser ms que una manera de agrupar el cdigo
en bloques lgicos, y de identificar estos bloques mediante un nombre. El nom-
bre de un procedimiento entra en la tabla de smbolos, y se le asocia la di-
reccin de la primera instruccin despus de la directiva 'PROC'.

   En el programa HELLO, tenemos un nico PROC, al que llamamos 'Entrada'.
Veamos las lneas detalladamente:

* mov ax,DATOS

   La etiqueta DATOS est en la tabla de smbolos, asociada al segmento de este
nombre. El ensamblador genera en el '.OBJ' una referencia, que ir despus en
el '.EXE', de manera que esta instruccin cargue en el registro AX el valor de
segmento necesario para que 'ax:0' apunte al primer byte del segmento datos.
Este valor variar de una vez que se cargue el programa a otra, pero el carga-
dor del DOS hace que siempre se asigne el valor correcto a AX.

* mov ds,ax

   Hace que DS, efectivamente, apunte al segmento de cdigo del programa. As,
podremos acceder a la cadena contenida en este segmento.

* mov dx, OFFSET Msg

   Carga DX con el offset de la etiqueta Msg dentro de su segmento. Ya que Msg
est al principio del segmento, dx se cargar con el valor 0. Aunque el progra-
ma pueda cargarse en cualquier punto de la memoria, el offset de algn dato o
alguna instruccin dentro de su segmento ser siempre el mismo, por lo que esta
instruccin no se incluye en la tabla de reubicacin del '.EXE'.

* mov ah,9
* int 21h

   Se invoca el servicio 9 de la interrupcin 21h del DOS. Este servicio escri-
en la pantalla la cadena apuntada por DS:DX (que en este caso ser la cadena
Msg). Se retorna al encontrar el carcter '$', que no se imprime. Podemos apre-
ciar que en el segmento DATOS aparece el smbolo '$' dentro de la propia
cadena.

* mov ax,4C00h
* int 21h

   Se invoca el servicio 4Ch de la interrupcin 21h. Este servicio retorna al
programa que invoc al programa actual (normalmente al COMMAND.COM), con un
nivel de error ('ERRORLEVEL') especificado en el registro AL. En este caso, se
retorna el valor 0 (que habitualmente indica ausencia de errores).

   Despus de cerrar el procedimiento 'Entrada' y el segmento 'CODIGO', encon-
tramos una ltima directiva, 'END', con el nombre del procedimiento como par-
metro. Esta directiva puede llevar un nico parmetro, opcional, que indica el
punto de entrada al programa. En caso de linkar varios '.OBJ' para generar un
ejecutable, slo uno de ellos puede especificar punto de entrada (pero necesa-
riamente alguno debe especificarlo), por lo que el resto de los mdulos termi-
nan su listado con un simple 'END'. En este caso, ya que 'Entrada' se asocia a
la primera instruccin del procedimiento, el punto de entrada es la instruccin
'mov ax,DATOS'.

   Antes de pasar a ver las directivas simplificadas de segmento, veamos un
punto importante de los ensambladores. Los ensambladores comerciales llevan
incorporado un evaluador de expresiones, de manera que en cualquier lugar donde
el ensamblador espere una constante puede aparecer una expresin que pueda
evaluarse en tiempo de ensamblado. Estas expresiones pueden llevar operadores;
podremos encontrar una lista de todos en el manual del ensamblador o en la ayu-
da online. Los ms importantes son los siguientes:

   +,-,*,/,MOD       Aritmticos
   OR, AND, XOR, NOT Lgicos
   SEG, OFFSET       Aplicados a una etiqueta, dan el valor de segmento donde
                     reside (se incluye una entrada en la tabla de relocaliza-
                     cin) y el offset dentro de su segmento
   SHL, SHR          Sintxis: X SHL Y. Devuelve el valor X desplazado a la
                     izquierda (derecha) Y bits.
   ()                Se utilizan para saltarse la precedencia de operadores

   Lneas vlidas utilizando estos operadores son las siguientes (suponiendo
que todas las etiquetas hayan sido definidas previamente):

	Msg      DW 55h SHR 2
	Variable DB 15 + OFFSET Msg
	mov ax,4+3*OFFSET Msg
	mov dx,2 + NOT 01010101b
	add ax,es:[bx+di+1+OFFSET Msg]
	sub si,(2Ah+13d)*2

   Son todas vlidas porque las expresiones que aparecen puede evaluarlas el
propio ensamblador para obtener valores numricos. Las siguientes instruccio-
nes, en cambio, aunque perfectamente inteligibles, son ilegales y el ensambla-
dor se quejar si las inclumos:

	mov ax,2+bx
	add dx,bx*ax
	mov cx,NOT dx

   Veamos ahora una versin del programa anterior utilizando las directivas de
segmento simplificadas. Veamos cmo se simplifica mucho:

=================8<============================8<===========================
.MODEL SMALL	; Un segmento de cdigo, otro con los datos y la pila
.STACK 200h		; 200h (512d) bytes de pila
.DATA			; Abre el segmento de datos
Msg	DB 'Hello, world!$'

.CODE			; Abre el segmento de cdigo, cierra el de datos
Entrada	PROC	; Abre el procedimiento 'Entrada'
	mov	ax,@data
	mov	ds,ax
	mov	dx,OFFSET Msg
	mov	ah,9
	int	21h		; Servicio 9: imprimir cadena
	mov	ax,4C00h
	int	21h		; Servicio 4Ch: retorno al DOS
Entrada	ENDP	; Cierra el procedimiento 'Entrada'

	END Entrada	; Fin del programa (punto de entrada 'Entrada'), cierra
				; el segmento de cdigo
=================8<============================8<===========================

   Las nuevas directivas utilizadas son las que comienzan con un punto. La
primera, '.MODEL', especifica el modelo de memoria que se va a utilizar. En
funcin de el modelo de memoria se seleccionan los nombres de los segmentos, de
manera que se pueda linkar el mdulo con otro mdulo escrito en un lenguaje de
alto nivel usando el mismo modelo de memoria. La directiva '.STACK' genera un
segmento de pila, de 1024 bytes en caso de que no se especifique el tamao. La
directiva '.DATA' abre el segmento de datos, cerrando el segmento anterior en
caso de que haya alguno abierto. La directiva '.CODE' abre el segmento de cdi-
go, cerrando (en este caso) el segmento de datos. Por fin, la directiva 'END'
es ampliada para cerrar el segmento abierto cuando aparece, en este caso el
segmento de cdigo.

   Ya que no sabemos el nombre que da el ensamblador a los distintos segmentos,
existen algunos smbolos que se definen automticamente al encontrar la direc-
tiva '.MODEL'. Estos smbolos representan el nombre de los distintos segmentos
generados, y son dos: @code y @data. Por eso, en la primera instruccin carga-
mos DS con @data, para poder acceder a 'Msg', que est en el segmento dado por
'.DATA'.

   El propio ensamblador genera el 'ASSUME...' al encontrar la directiva
'.CODE'. Como vemos, no es necesario preocuparse por casi nada al usar las
directivas simplificadas de segmento. De hecho, ya no es habitual encontrar
programas escritos con las directivas antiguas. Estas directivas se aadieron
para facilitar el desarrollo de programas con mdulos en distintos lenguajes,
ya que la tarea se complica mucho usando las directivas clsicas.

   En el siguiente captulo veremos el ltimo concepto que nos queda por ver
de microprocesadores: los flags. Veremos algunas instrucciones nuevas y alguna
interrupcin nueva, vindolo todo con un pequeo programa de ejemplo. De aqu
en adelante, iremos cubriendo distintos temas progresivamente, de manera que
se vean ejemplos de todos los usos habituales del lenguaje ensamblador. De
esta manera, aunque el curso no ser muy til como referencia de ASM, quien
lo siga habr visto la mayora de los aspectos del ASM y podr abordar cual-
quier proyecto en este lenguaje, que es cuando realmente adquirir verdadero
dominio del lenguaje. Os recomiendo que os hagis al menos con dos manuales o
guas de referencia: una con las instrucciones del 80x86, y otra con las
interrupciones de la BIOS y el MSDOS. Sobre las instrucciones no me atrevo a
recomendar ninguna, mientras que sobre las interrupciones tenis por ah unos
documentos, escritos por Ralph Brown, denominados INTERxxA.ARJ, INTERxxB.ARJ e
INTERxxC.ARJ (xx es la versin, la ltima es la 33, creo) con la ms completa
referencia de interrupciones que existe (son muchos megas de texto!). Son de
dominio pblico, por lo que las encontraris en bastantes BBS. Ah tendris
todo lo que queris saber sobre los usos de las diferentes interrupciones.

   Salut :-)

   Jon