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

Por nmt
numit_or@cantv.net

=================================
INSTRUCCIONES Y DIRECCIONAMIENTOS
=================================

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



  - Intrucciones del i8086

  - Identificadores: nombres y etiquetas

  - Sintaxis de una instruccin
	 Operandos y direccionamientos.
		 Registros.
		 Inmediatos.
		 Memoria directa.
		 Memoria indirecta: operador OFFSET, especificadores.
			             de ndice.
		 Desplazamiento de direccin o indexado indirecto.
		 Direccionamiento relativo a base: operadores
				     aritmticos.
		 Indexado de base: Indexacin en el 80386 y superiores.

  - Definicin de variables
	 Cadenas de caracteres
	 Constantes numricas
	 Directiva EQU

  - Instrucciones de Control y el registro de banderas

  - Ejemplo 
			




------------------------
Instrucciones del i8086
------------------------
A  manera  de referencia,  presentamos  una  lista  con  las instrucciones del 
procesador 8086, el ms simple de la serie que estudiamos:

	 de transferencia y asignacin: mueven datos desde alguna localidad a 
		otra;  la  localidad  puede ser un registro del procesador, un 
		registro  de algn dispositivo de entrada/salida del  sistema, 
		o  una  celda  en  la  memoria.  Tambin  permiten  asignar un 
		contenido   a   cualquier   localidad.   Las   operaciones  de 
		transferencia del 8086 son:
		

	MOV		MOVe: mover datos
	LEA		Load Efective Address: cargar direccin efectiva
	XCHG		eXCHanGe: intercambiar datos
	XLAT		Recorrer una tabla		
	LDS		Load Data Segment: cargar segmento de datos
	LES		Load EXended Segment: cargar segmento extendido
	LAHF, SAHF	Load/Store AF flag: cargar/almacenar indicador AF
	PUSHF, POPF	Meter_en\Sacar_de la pila el registro de indicadores 			
				
	 sobre cadenas de caracteres: designan operaciones de transferencia y
		comparacin de cadenas de caracteres

	CMPS		Compare String: comparar cadenas
	SCAS		Scan String: comprar cdenas
	LODS		Load String: Cargar cadenas
	STOS		Store String: Almacenar cadenas

	 de transformacin: designan las operaciones aritmticas, lgicas y
		 de rotacin-desplazamiento de bits en localidades.

	ADD		Add: sumar
	ADC		ADd with Car: sumar con acarreo
	AAA		ASCII Adjust then of Add: ajustar ASCII despus de la suma
	DAA		Decimal Adjust then of Add: ajustar decimal despus de sumar
	SUB		Substract: substraer
	SBB		Substract: substraer con acarreo negativo
	AAS		ASCII Adjust then of Substract: ajustar ASCII despus de restar
	DAS		Decimal Adjust then of Substract: ajustar decimal despus de restar
	MUL		Multiply

	IMUL		Integer Multiply
	AAM		ASCII Adjust then of Multiply: ajustar ASCII despus de multiplicar
	DIV		Divide: dividir

	IDIV		: divisin con signo
	AAD		ASCII Adjust then of Divide: ajustar ASCII despus de Dividir
	INC		Increace: incrementar
	DEC		Decreace: decrecer
	NEG		Negate: negar en complemento a dos
	CMP		Compare: comparar
	CBW		Convert Byte in Word: convertir byte en palabra		
	CWD		Convert Word in Dword: convertir palabra en doble palabra

	. . . . . .

	NOT		Not: negar (los bits 1 los pone en 0 y viceversa)
	AND		And, conjuntor lgico 
	OR		Or, disyuntor lgico
	XOR		eXclusive OR, disyuntor lgico exclusivo
	TEST		Test, aplica una conjuncin sin cambiar los operandos

	. . . . . .

	SHL/SAL		Shift Left, desplazar bits a la izquierda
	SHR		Shift Right, desplazar bits a la derecha
	SAR		Shift Artmethic Right, desplazar bits a la derecha
	ROL, ROR	Rote Left/Right, rotar bits a la izquierda/derecha
	RCL, RCR	Rote Left/Right, rotar a bit de acarreo a la izquierda/derecha

	 de entrada-salida: describen operaciones de transferencia entre el procesador
		y los dispositivos de entrada/salida.

	IN		Into, Introducir datos en un puerto
	OUT		Out, Obtener entrada desde un puerto


	 de control de secuencia: controlan el flujo en un procedimiento. 
	
	JMP		Jump, salto incondicional
	J?, JN?		Jump if ?, salto condicional que depende de alguna de las
			banderas	
	LOOP		Loop, bucle
	JCXZ		Jump if CX ?, salto condicional que depende del valor en CX
	INT		INTerrupt, interrumpir
	IRET		INterrupt Return, Regresar de una interrupcin 

	 de control de subrutinas: controlan el flujo entre varios procedimientos.

	CALL		Call, llamar una procedimiento
	RET		RETurn, regresar a otro procedimiento
	PUSH		Push, meter en la pila
	POP		Pop, sacar de la pila
	ENTER		Crea una pila para un procedimiento (i386 y posteriores)

	 de control del procsador: permiten actualizar los bits del registro de los
		indicadores (flags) y sincronizar el procesador con sucesos externos:

	CLC, CMC, STC	CLear/SeT C flag, Limpiar/establecer indicador de acarreo 
	CLD, STD	CLear/SeT D flag, Limpiar/establecer indicador de direccin
	CLI, STI	CLear/SeT Interrupts, Limpiar/establecer interrupciones
	HALT		Halt: parar
	WAIT		Wait: esperar hasta que se niegue la seal busy#
	ESC		Escape
	LOCK		Lock: cerrar bus
	NOP		No OPeration, ninguna operacin

Ya hemos tenido oportunidad de ver cmo trabajan algunas de las instrucciones de
transferencia: MOV, LEA; tambin una de control de secuencia: INT.

Cada instrucin tiene sus reglas de uso. Por ejemplo, la instruccin MOV permite

	 mover datos desde un registro general a otro: MOV AX, BX;
	 mover datos inmediatos a un registro general MOV AX, 9;
	 mover datos desde una localidad de memoria a un regisro
          general: MOV AX, nombre;
	 mover datos desde un registro regisro a una localidad de
	  memoria: MOV nombre, DX;

No permite:
	 mover datos de una localidad de memoria a otra: 
	  MOV nombre1, nombre2
	 mover datos desde una localidad de memoria a un registro
	  de segmento: MOV DS, nombre_de _segmento

Vistas as en fro, seguro que esta lista tendr poco sentido. Ya tendremos 
ocasiones de jugar con ellas y, en ese juego, descubrir su uso y potencia.


-------------------------------------
Identificadores: nombres y etiquetas
-------------------------------------
Antes  de  continuar con  las instrucciones,  es bueno precisar una diferencia 
en los identificadores usados. Los que se emplean para sealar la direccin de
algn dato los llamamos nombres y los empleados para referirse a una direccin
de una instruccin, los llamamos etiquetas (labels).

En el cdigo presentado, 

; --------------------------------------------------------
	.data
  string        db      'Hola gente!', 24h
; --------------------------------------------------------
	.code
  main	proc 	far
  _init:
	mov	ax, @data 
	mov	ds, ax
  _display:
	lea	dx, string
	mov	ah, 1001b
 	int	21h 
  _pause:
	mov	ah, 16
	int	16h
  _exit:
	mov	ax, 0
	ret
  main	endp
; --------------------------------------------------------

la palabra "string" refiere a una direccin de  un  dato;  en  este  caso  una
constante del tipo cadena de caracteres. Se trata de un nombre.

En  cambio,  todas  las palabras que en el segmento de cdigo son seguidas por 
dos puntos: _init, _display, _pause, _exit (el prefijo '_'  no es relevante en 
este caso,  se colocan para evitar poner una palabra  reservada  del  lenguaje 
ensamblador) son etiquetas que marcan direcciones de instucciones.

En un identificador podemos usar las letras desde la  A  a  la  Z,  caracteres
especiales como '?', '_', '$', '@'.  Se pueden usar tambin nmeros y el  '.', 
pero nunca como el primer caracter.

Debe  tenerse  cuidado con el uso de '@',  ya que es usado a veces en smbolos
especiales.

Las  letras  maysculas  son  tratadas  como iguales,  a no ser que se indique
sensiblidad para la diferencia entre maysculas y minsculas.


----------------------------
Sintaxis de una instruccin
----------------------------
La  sintaxis  se refiere excusivamente  al aspecto formal de un  lenguaje,  a
las  reglas  para construir frmulas correctas  en  l,  sin  considerar  sus
significados o contenidos.

Desde  el  punto  de  vista  sintctico un lenguaje es casi exclusivamente un 
conjunto de combinaciones que concuerdan con ciertas reglas de arreglo.  Para 
que un enunciado signifique, debe estar bien construdo,  sus elementos deben 
estar  ordenados  correctamente.  Si  el programa est escrito correctamente, 
respetado  las reglas sintcticas,  entonces  no  debera  conducir  a error, 
debera correr perfetamente (correccin de un lenguaje de programacin).

La sintaxis puede variar de un lenguaje de programacin  a  otro.  Inclusive,
puede variar de un ensamblador a otro.  Tal es el caso,  por ejemplo,  de  la 
sintaxis de Intel frente a la sintaxis de AT&T para los mismos  procesadores. 
MASM y TASM tienen prcticamente la misma sintaxis:  Intel.  NASM  posee  una 
sintaxis estilo Intel,  pero con algunas diferencias respecto a MASM-TASM. El ensamblador de GNU, GAS, sigue la sintaxis de AT&T, la clsica de UNIX.

Para ilustrar la diferencia:

	MOV	ECX, 5		; Intel: mover 5 a ecx.
	MOV	EAX, ECX 	; Mover a eax, lo que hay en ecx

es en GAS:

	MOVL	$5, %ECX	; AT&T: mover 5 a ecx,
	MOVL	%ECX, %EAX	; Mover a eax, lo que hay en ecx

Como puede observarse,  cambia el orden de los operandos, cambia la sintaxis 
de un ensamblador a otro. Pero el significado es el mismo,  se  conserva  la 
semntica.  Tiene  que  ser  as,  porque  el dominio de aplicacin de estos 
enunciados es el mismo: un procesador ix86.

En  ambos casos hay tambin otro aspecto  en  comn:  una  operacin  y  dos 
operandos.  En  general  ese es el formato de una intruccin en ensamblador: 
una operacin seguida por sus operandos.

Toda  operacin tiene una ariedad,  la propiedad que designa la cantidad de 
operandos  sobre los  cuales se  aplica.  Hay  operaciones  ceroarias  (las 
constantes, que no se aplican a ningn operando), unarias (que se aplican a 
un solo operando), binarias (que se aplican a dos operandos), etc.

La  instruccin  MOV  y  la   instruccin  LEA,   que  son  operaciones  de 
transferencia, son ambas binarias.  La instruccin INT que hemos usado,  es 
una operacin unaria:

	INT	21h		; un nico operando

Con las citadas diferencias, hay ciertos aspectos sintcticos que respetan 
los lenguajes ensambladores que he visto hasta ahora:  la sintaxis general 
de una instruccin:

[identificador]	operacin	[operando(s)]	[; comentario]

El  identificador  designa  el  nombre  de  un  dato o la etiqueta de una 
instruccin.  La  operacin puede ser un trmino que defina un tipo en el 
rea de datos o una operacin del procesador,  que  se  halle  en el rea 
del cdigo. Los operandos, cuando los hay,  proporcionan  la  informacin 
necesaria para  una  operacin.  Los  comentarios  son  descripciones  en 
lenguaje  natural  de los pasos del algoritmo que est realizando nuestro 
cdigo. Son indicaciones que no procesa el ensamblador, slo se usan para 
aclarar  lo  que  se  est  haciendo.  Para  convertir  una  expresin en 
comentario  y  evitar  que sea  procesada,  slo le prefijamos un punto y 
coma (;).

A contiuacin dos ejemplos de instrucciones en lenguaje  ensamblador;  la 
primera  desiga  una  cadena de caracteres en una direccin del  rea  de 
datos que identificamos con el nombre "string".  La  segunda  instruccin 
designa  una  instruccin  en  una  direccin  del  rea  de  cdigo  que 
identificamos con la etiqueta "_init", seguida de dos puntos:

identificador  operacin	operando	comentario

  string           db      'Hola gente!', 24h	; no hay

  _init: 	   mov	       ax, @data 	; no hay

En la sintaxis Intel, que es la que estudiamos,  las operaciones binarias 
en las instrucciones de transferencia consideran el segundo operando,  en
el extremo derecho, como origen y al primero,  inmediatamente despus del 
nombre de la instruccin, como destino:

	MOV	EAX, EDX	; Mover a EAX lo que est en EDX
	LEA	EDX, string	; Cargar en EDX la direccin de string

Cada instruccin tiene su limitaciones,  las  cuales sern explicadas en
su momento.



Operandos y direccionamientos
-----------------------------
El  tema  de  los  operandos  de   las  instrucciones  est  ntimamente 
relacionado   con  el  de  los  direccionamientos,   debido  a  que  las 
operaciones   se   realizan  sobre  localidades  del  sistema  que  debe  
identificar:  todo operando es una localidad o est en una localidad del 
sistema. Esta localidad no se limita a una direccin de memoria: tambin 
un registro del  procesador es una localidad del sistema.  Por  eso,  un 
tipo de operando implica un  tipo  de  direccin  y  exige  un  modo  de 
localizacin.

	*NOTA*
	Para localizar un operando, el procesador dispone de una  unidad  
	de  ejecucin,  la  EU  (Execution Unit),  donde  se  hayan  los 
	registros  de  propsito  general  y la unidad lgico aritmtica 
	(ALU: Aritmetic Logic Unit). Su propsito es la ejecucin de las
	instrucciones:

		EU:		:	       BIU:
	Unidad de Ejecucin	:	Unidad de Interfaz
	 ---------------	:	     del Bus
	|   ah	|  al	|	:
	 ---------------	:
	|   bh	|  bl	|	:
	 ---------------	:
	|   ch	|  cl	|	:
	 ---------------	:
	|   dh	|  dl	|	:
	 ---------------	:	 ---------------
	|	sp	|	:	|	CS	|
	 ---------------	:	 ---------------
	|	bp	|	:	|	DS	|
	 ---------------	:	 ---------------
	|	si	|	:	|	SS	|
	 ---------------	:	 ---------------
	|	si	|	:	|	ES	|
	 ---------------	:	 ---------------    ---------
		|		:		|	   | Unidad  |
		 ----------------------------------------->| Control |-> Bus
		|		:		|	   | de BUS  |
	 ---------------	:		|	    ---------
	|  ALU: Unidad  |	:	     -------
	|lgico-aritmet.|    ---:-----------|   1   |
	 ---------------    |	:	     -------
	| CU: Unidad de |   |	:	    |   2   |    Cola de
	|    Control	|   |	:	     -------   Instrucciones
	 ---------------    |	:	    |   3   |
	|  Registro de  |   |	:	     -------
	|    Banderas	|   |	:	    |   4   |
	 ---------------    |	:	     -------
			    |	:	        :
	 ---------------    |	:	     -------
	|   Puntero de  |---	:	    |   n   |
	| Instrucciones	|	:	     -------
	 ---------------	:
				:

	Para  ejecutar  las instrucciones,  la  EU debe recibirlas de la
	unidad de interfaz del bus (BIU),  que controla la transferencia
	de datos de la memoria a la EU. La BIU contiene los registros de 
	segmento, controla el BUS de datos y la cola de instrucciones.

	La EU pide instrucciones a la BIU,  le  notifica cuando necesita
	datos en memoria o en un dispositivo de E/S,  o  cuando necesita
	instrucciones en la cola.  La  BIU  pasa  la  instruccin que se
	encuentra  en el tope de la cola y, mientras la  EU  ejecuta  la
	instruccin, la BIU va en busca de una nueva instruccin para la 
	cola.  La  EU  queda  encargada  de  interpretar  el  cdigo  de 
	operacin y realizar las operaciones respectivas: decide cul es 
	el operando de origen y cul el de destino y permite que la  ALU 
	lleve a cabo la operacin.

	Como  puede  observarse,  un  operando no parece ser ms que una
	localidad  en  el sistema  sobre  el  cual se ha de realizar una
	operacin.  La  interpretacin  del  operando  es  un proceso de
	ubicacin de una localidad, un direccionamiento:  los  operandos
	posibles equivalen a modos de direccionamiento posibles.


Un  operando  es  una  fuente  de  datos  para  una instruccin. Algunas 
instrucciones  no  tienen  operandos.  Pero  cuando  tienen  ms de uno, 
decimos (en la sintaxis Intel) que el primero es el destino y el segundo 
la fuente de la operacin. En la operacin, la fuente no cambia, pero el 
destino s es afectado.

Hay varios tipos de operandos o de direccionamientos:

	 Registros:  representado  por  alguno  de  los nombres de los
	  registros   que  ya  hemos  mencionado.  En  las  operaciones 
	  binarias,  los  registros  pueden  ocupar  cualquiera  de los
	  operandos.   Adelantamos  que  las  operaciones  donde  ambos
	  operandos son registros son las ms rpidas y cortas,  ya que 
	  los registros estn en el mismo procesador.

	  	MOV	EBX, EAX

	 Inmediatos:  son  valores  o expresiones constantes que slo
	  pueden ocupar el operando fuente, ya que, por ser constantes,
	  no pueden cambiar. La longitud de los datos queda estipulada
	  por el destino.

		MOV	AL, 5

	 Memoria  directa:   son  valores  que  hacen  referencia  a 
	  localidades  de  memoria.  No hay instrucciones donde ambos 
	  operandos sean direcciones de memoria,  pero un operando de 
	  memoria puede ser la fuente o el destino de una instruccin.

		m1	DW	0		; dato con un tamao WORD (16 bits)
		m2	DB	0		; dato tamao BYTE (8 bits)

			...

			MOV	m1, 10		; mover 10 a la localidad llamada m1
			MOV	AX, m1		; mover el contenido en m1 a AX

			LEA	DX, m2		; poner en DX la direccin de m2
			MOV	CX, DX		; mover a CX la direccin de m2


		*NOTA*
		En este tipo de direccionamiento,  la EU debe calcular 
		la direccin efectiva (EA: Efective Address)  para una 
		direccin  en la memoria que debe ser indicada  en  la 
		instruccin.  Dicho  clculo  se  efecta  sumando  la 
		direccin  efectiva  (que  se   interpreta   como   un 
		desplazamiento [offset]) al valor en  el  registro del 
		segmento de datos DS,  supuestamente la direccin base 
		de dicho segmento.


	 Memoria  indirecta:  estos  tipos de operandos constan de un 
	  registro base y un ndice.  Como  base se usan los registros
	  de segmento y como ndice los registros  BX,  DI,  SI  y BP.
	  Estos  registros  ndices  contienen  la direccin efectiva. 
	  Para diferenciar un operando de registro  de un operando  de 
	  registro de memoria indirecta,  se  pone el  registro con la 
	  direccin efectiva entre corchetes:  los  especificadores de
	  ndice.

	  Los registros  ndices  son asociados a regitros de segmento 
	  muy especficos.  BX, DI y SI son  asociados con  DS: DS:BX,
	  DS:DI y DS:SI.  De  esta  manera se procesan objetos  en  el
	  segmento de datos.

	  El  registro  BP  est  asociado al registro del segmento de
	  pila  SS:  SS:BP.  Este tipo  de instrucciones son tiles en 
	  programas donde hay rutinas remotas  y  es  necesario  pasar
	  parmetros.

	  Como  la  direccin  efectiva  indica  una  localidad  en la 
	  memoria relativa  a  un segmento,  no  el  contenido  de  la 
	  localidad, se usan instrucciones especiales;  una  de  estas 
	  instrucciones es LEA (Load Efective Address):

			LEA	DI, mx

	  Tambin puede usarse el operador OFFSET (desplazamiento):

			MOV	DI, OFFSET mx

	  Las  dos instrucciones son  equivalentes,  salvo  cuando  la 
	  direccin  de memoria,  en  este  caso  indicada  por  "mx",
	  refiere a una variable local,  las cuales son ubicadas en la 
	  pila, no en el segmento de datos.  En este caso, debe usarse 
	  la instruccin LEA.

	  Un ejemplo de este tipo de operando ya lo hemos presentado:

			LEA	BX, m2		; poner en DX la direccin de m2
			MOV	[BX], 80	; mover 80 a la direccin m2, en DX
						; Notar la necesidad de usar los
						; corchetes para indicar direccin
						; de memoria

	  Si el destino es un operando de memoria indirecta, entonces,
	  el origen  debe ser un registro o un operando inmediato.  Si
	  la fuente es operando de memoria indirecta,  el destino debe
	  ser un registro.

		*NOTA IMPORTANTE*
		Especificadores de ndice
		Ntese el uso de corchetes para indicar  direccin de
		memoria. Si hubisemos escrito:

			MOV	BX, 80

		slo estaramos poniendo 80 en BX, no en la direccin
		indicada por el contenido de BX.

		A  los  corchetes  les  llamamos  especificadores  de 
		ndice. Se usan para indicar referencia a memoria.

		La   referencia   a   memoria   se  realiza  como  un
		desplazamiento (offset) dentro de un segmento. Quiere 
		decir que siempre se apoyan en el valor que  contiene 
		un registro de segmento, como direccin base,  al que 
		se   suma  el  valor  del  operando,   que  sera  el 
		desplazamiento dentro del segmento.  Respecto  a  los 
		datos, el registro DS es el tomado por defecto en las 
		instrucciones.

		Esto quiere decir que la instruccin:

			LEA	BX, m2
			MOV	[BX], 80	; pone 80 en DS:BX

		pone  80  en  una  localidad  igual  a  la  suma del 
		contenido de DS ms el el valor correspondiente a la 
		direccin que indica elnombre m2.

		Cualquier  referencia  en  corchetes a los registros 
		ndices, implican operando de memoria indirecta.			

		Luego tendremos que ver  cmo  se usan correctamente 
		los   corchetes   especificadores   de   ndice   en 
		instrucciones    con    direcciones    de   memoria, 
		especialmente en el manejo de arrays.


	 Desplazamiento de direccin o indexado indirecto:  Un tipo 
	  de  operando  complejo  usa  direccin  de memoria directa 
	  (generalmente indicadas con nombres) y un registro ndice:

			MOV	AL, 1		; AL = 1
			MOV	DI, 4		; DI = 4
			MOV	m1[DI], AL	; Mueve 1 a m1+4

	  La ltima instruccin de la  secuencia anterior,  mueve el 
	  contendio de AL,  la cantidad contenida en DI ms adelante
	  de la direccin sealada por m1.

	  Aqu,  los corchetes,  los  operadores especificadores  de
	  ndice,  funcionan de manera  similar  a un sgino de  suma
	  "+".

	  Los  direccionamientos   indexados  son  muy  tiles  para 
	  referenciar a las entradas de tablas de datos.


	 Direccionamiento   relativo  a  base:  aqu  la  direccin
	  efectiva del operando se obtiene sumando un desplazamiento
	  a uno de los dos registros base:  BP  o  BX. En este caso,
	  estos  registros  tienen la direccin del desplazamiento a 
	  los que se le suma un escalar que indica el desplazamiento, 
	  que puede ser un valor numrico constante: 1, 2, 4 u 8.

			MOV	m2, 80
			LEA	BX, m2
			MOV	[BX+2], 80	; pone 80 en DS:BX+2

	  Esta  instruccin  pone  80  dos  bytes ms adelante de la
	  direccin indicada por m2.

		*NOTA*
		Operadores aritmticos
		Aqu  podemos  observar  el uso de un operador nuevo 
		para  indicar  suma:  "+".   Hay  varios  operadores 
		aritmticos para indicar, adems de suma (+),  resta 
		(-), multiplicacin (*)  y  divisin  (/).  A  estos 
		operadores aritmticos habra que  aadir operadores 
		lgicos:    conjuncin   (and),   disyuncin   (or), 
		disyuncin  exclusiva  (xor),  negacin (not).		 

	 Indexado  de  base:  la  direccin efectiva es la suma del 
	  registro  base,  BX,  un registro ndice,  SI o DI,  y  un 
	  desplazamiento opcional, indicado ste por un escalar.

			LEA	BX, m2
			MOV	SI, 8
			MOV	AX, [BX][SI+2]

	  Esta instrucin pone en AX lo que se encuentre (SI=8)+2=10 
	  bytes delante respecto a la direccin referenciada por m2.

		*NOTA IMPORTANTE*
		Indexacin en el 80386 y superiores:
		A  partir  del  intel  80386,  es posible un modo de 
		direccionamiento semejante al indexado de base, pero 
		donde  se  permite  el  uso  de  uno o ms registros 
		generales, ya no exclusivamente los registros base o 
		ndice, en combinacin  con  un  desplazamiento y un 
		factor de escala:

			MOV	EAX, [ECX*2+ESP+4]

		La  instruccin  mueve  a EAX lo que se encuentra en 
		una localidad de memoria indicada por  el  contenido 
		en ECX por 2 ms el contenido de ESP,  que apunta el  
		tope de la pila, ms 4.

		Ntese   el   uso   del   operador   aritmtico   de 
		multiplicacin '*',  que  multiplica el contenido de 
		ECX  por  2.  Ya  hablaremos  en  su  turno  de  los 
		operadores.

		Se  trata  de  un direccionamiento  como el indexado 
		de base, pero que incluye registros generales usados
		ndices.


------------------------
Definicin de variables
------------------------
Como ya hemos visto, en el segmento de datos se definen constantes y 
variables del programa. Tambin pueden definirse regiones de trabajo 
y reas para entrada y salida de datos.

Para definir variables, seguimos el siguiente formato:

	[nombre]	Dx	expresin

El nombre  es el identificador a travs del cual haremos referencia 
al dato. Este nombre es lo que se usar como referencia a localidad 
de memoria en los operandos de memoria  en  las  instrucciones  del 
cdigo.

Dx  es  la  directiva  para  definir  el  tamao  del  dato. La "D" 
significa definir, la "x" corresponde a una letra que nos  dice  el 
tamao del dato:

	DB	(define byte): define un dato con tamao de un byte 
				(8 bits)

	DW	(define word):  define  un  dato  con tamao de una 
				palabra (word= 2 bytes = 16 bits)

	DD	(define double word)  define  un dato con tamao de 
				una palabra doble (double word = 32 
				bits)

	QD	(define quadruple  word)  define  un  dato  con  un 
				tamao de  cuatro  palabras  (=  64 
				bits)

	DT	(define ten byte)  define  un  dato  de 10 bytes de 
				longitud (80 bits)

La  expresin  es  el valor con el que inicializamos el dato. Si no 
queremos inicializarlo, podemos usar el signo '?':

	variable1	db	?
	variable2	dw	1204h

La  expresin  puede  ser  definida  como  un  conjunto  de valores 
separados por comas:

	variable3	db	10, 11, 12, 13

En  la  definicin  anterior en realidad hemos definido un array de
cuatro datos con un tamao de un byte cada uno. Para obtener uno de 
estos valores, necesitamos indexar en el array.

	mov	al, variable3+3
	mov	ah, variable3+2
	mov	cl, variable3+1
	mov	ch, variable3

Tambin podemos usar los _especificadores_de_ndice_:

	mov	al, variable3[3]
	mov	ah, variable3[2]
	mov	di, 1
	mov	cl, variable3[di]
	dec	di			; la instruccin "dec" (decrementar)
					; disminuye o decrementa en uno el
					; contenido de su operando, sea
					; registro u operando de memoria
	mov	ch, variable3[di]

Si  queremos  reservar  un buffer grande (rea para movilizacin de 
datos),  podemos usar la directiva DUP (Duplicar),  que  multiplica 
tantas veces especefiquemos un valor constante una unidad de  dato. 
El formato de DUP es:

	[nombre]  Dn  contador_de_repeticiones  DUP  expresin

	buffer1	db	512 dup (?)
	EFES	dw	 25 dup (0FFFFh)
	OCHOS	dB	  4 dup ( 3 dup (8) )


Cadenas de caracteres
---------------------
Para definir constantes del tipo cadenas de caracteres, usamos  la
la directiva DB (define byte):

	[nombre]	DB	'Cadena de caracteres'

Puede  preguntarse  cmo  es posible que se defina como 'byte' una
secuencia  que  supera  el  tamao  de  un byte (recurdese que un
caracter tiene un tamao de un byte). Debe recordarse tambin  que 
se  puede  definir  como  byte una serie de datos, cada uno con el 
tamao de un byte y  separado por comas. Es lo mismo con la cadena 
de caracteres,  slo  que  ahora los caracteres no estn separados 
por una coma de otro.

Obsrvese  que  la cadena est entre apstrofos. Si la cadena va a
contener un apstrofo, entonces debe definirse entre parntesis:

	string1		DB	"numit_or's programming page"


Constantes numricas
---------------------
Para definir valores aritmticos y direcciones de memoria,  se usan 
constantes  numricas  que  no  van  entre comillas nunca y que van 
seguidas por un especificador de base.

La base puede ser de cuatro tipos:

	Decimal: correspondiente al formato decimal. Es la
		base por defecto,  pero puede especficarse
		sufujando la cifra con uuna 'd':

			210d

	Hexadecimal: el ms usado,  corresponde al formato
		hexadecimal. Debe ir sufijada la cifra con
		la letra 'h'.  Si  la cifra inicia con una
		letra, entonces debe prefijarse con un 0:

			0AB7h
			216h

	Binario:  define  dgitos  binarios 0 y 1 seguidos 
		por la letra 'b'.  Se  usa  normalmente en 
		operaciones lgicas  y  en  el  manejo  de 
		bits:

			0000 0010 0001 0110 b

		equivale a 216h

	Real:  para  definir  valores  reales  se  usa una 
		constante  decimal  o  hexadecimal seguida 
		por  el  especificador  de   base  R.   El  
		ensamblador  reemplazar   este  valor  en  
		formato de punto flotante para el uso  del 
		coprocesador  matemtico:

			450R25

Directiva EQU
--------------
Para lograr la definicin de constantes numricas podemos  usar  la 
directiva EQU. En realidad la directiva no define  un  elemento  de 
dato: define un valor que el ensamblador puede usar  por  un  valor 
numrico  o de alguna instruccin. De esa manera,  la directiva EQU 
ayuda en la legibilidad y claridad del programa:

BLACK		EQU	0
BLUE		EQU	1
GREEN		EQU	2
CIAN		EQU	3

Despus de estas lneas, podemos usar la palabra BLACK en vez de 0, 
BLUE en vez de 1, etc; se ayuda as a memorizar valores constantes.

Tambin puede resumirse una expresn en un trmino simple:

	precio_a_pagar	DW	?
	...		
	pap		EQU	precio_a_pagar
	invoke		EQU	call

	*NOTA*
	Algunos  ensambladores  modernos  incluyen   la   directiva 
	TEXTEQU para datos de texto:

		nombre TEXTEQU	<texto>



---------------------------------------------------
Instrucciones de Control y el registro de banderas
---------------------------------------------------
Hay algunos conceptos de programacin que son  independientes  del
lenguaje de programacin a usar.  Dichos  conceptos tienen que ver
con la forma en que deben disearse los  programas,  en  cuanto  a
estilo y forma. Se han desarrollado varias tcnicas para conseguir 
correccin lgica, eficiencia,  comprensibilidad  y  facilidad  de 
mantenimiento  del  cdigo  de  un  programa:  diseo  ascendente, 
programacin modular, cdigo estructurado,  programacin orientada 
a objetos.

Pareciera  una  complicacin  adicional  mencionar  cuestiones  de 
estilo y problemas de diseo de software en  estas circunstancias. 
Sin embargo,  cuando nos referimos a las instrucciones de  control 
es necesario mencionar algunas cuestiones vinculadas con el uso de
tales instrucciones,  ya  que es sobre stas parece recaer el peso 
de la problemtica referida  a  la  representacin de algoritmos a 
travs de lenguajes de  programacin:  la  claridad  y  correccin 
lgica de un programa  parece  reposar  en un alto grado sobre sus 
instrucciones de control.

En general,  un  programa es una secuencia de pasos que conduce de
una entrada a una salida,  y  la llegada de un punto a otro reposa 
sobre condiciones la satisfaccin de  una  regla  que  controla el 
flujo del programa:  las  sentencias  que  usamos  para repesentar 
algoritmos son reglas que establecen condiciones muy precisas para 
pasar de un punto a otro.  Las  instrucciones  de control  son  el 
principal  mecanismo de representacin de estas reglas.  Cuando en 
algn momento del programa no se satisface  cierta  condicin,  el 
programa debe tener a mano un mecanismo para abortar la operacin.
Se trata uno de los principios  importantes de la disciplina de la
programacin  y  sobre  los  cules  reposa  cualquier  evaluacin 
importante de un programa.

Las  instrucciones  de  control  consisten en evaluaciones de cuyo
resultado depender una desicin dentro del programa.  En lenguaje
ensamblador, para los procesadores que estudiamos, existen varias.
Hablaremos primero de los saltos condicionales, que establecen que 
debe tomarse una  accin,  especificada  por  una  rutina  en  una 
direccin determinada --a la que debe  saltarse,  si se cumple  la 
condicin. Como ejemplo, estn las siguientes operaciones unarias:

	je/jz: salta si es igual/salta si es cero
	jne/jnz: salta si no es igual/salta si no es cero

El formato de estas instrucciones es:

	instruccin	direccin

El operando "direccin"  puede  ser un  dato directo con indicando 
una localidad de memoria, puede ser una variable o un registro con 
la direccin donde el programa pasar el  control.  Tambin  puede 
ser un  operando  indirecto  (un  registro  entre  corchetes:  los 
especificadores) que indique la  direccin  donde  est otro valor 
que indica la direccin final donde se ha de pasar el control. Las
siguientes  instrucciones  hacen  que se realice al final un salto
a la localidad contenida por la variable "dir",  dependiendo de si
se ha cumplido una condicin:

	lea	si, dir
	je	[si]

Las instrucciones de salto condicional je/jz y jne/jnz, revisan un 
bit particular en el registro de banderas:  el bit ZF (Zero Flag). 
Si este bit est activado,  la instruccin je/jz pasar el control 
a la instruccin  en  la  direccin  indicada,  sino  el  programa 
continuar en  la  siguiente  instruccin.  La instruccin jne/jnz 
tiene el comportamiento contrario,  pasa el control a la direccin 
indicada si el bit ZF no est activo.

Esta circunstancia nos da oportunidad de introducirnos al registro 
de banderas o indicadores.

Hasta el 80386,  el registro de banderas tena un ancho de 16 bits 
de los cuales 9 eran comunes con los procesadores anteriores de la 
serie ix86. Estos bits tienen sus nombres:

	OF (Overflow Flag, desbordamiento)
	DF (Direccin)
	IF (Interrupcin)
	TF (Trampa)
	SF (Signo)
	ZF (Cero)
	AF (Acarreo auxiliar)
	PF (Paridad)
	CF (acarreo)

Cada  bandera ser explicada en su  momento  oportuno.  Hablaremos 
ahora de la bandera de cero. Este indicador seala el resultado de 
una operacin aritmtica de comparacin.  Quiere decir que,  si la 
operacin resulta en cero,  la bandera se activa,  sino se pone en 
blanco o cero.

Aqu  tenemos ya un primer mecanismo de evaluacin de condiciones:
se  realiza  una  operacin,  si el resultado es cero, activar la
bandera de cero y se saltar o  no a otra instruccin, dependiendo
de si se usa je/jz o jne/jnz.

Existen   instrucciones   especiales   para  hacer  este  tipo  de 
comparaciones:

	test
	cmp

La  instruccin  test  es una operacin binaria que somete a ambos 
operandos a una prueba de conjuncin (funcin and).  La conjuncin 
da como resultado verdad o 1 slo cuando ambos trminos son verdad 
o 1.  Quiere  decir que si ambos trminos de  comparacin estn en 
cero, el resultado ser cero y se activar la bandera de cero:

	test	al, al		; prueba de conjuncin
	jz	dir1		; salta si AL es cero
	dec	al		; si no salta se decrementa AL
dir1:	inc	al		; se incrementa en 1 el contenido de AL 

Esta  instruccin  incrementar  en  1 el valor en al si durante la 
prueba contiene cero, en caso contrario se decrementar su valor en 
uno antes de restablecerse este decremento.

La instruccin cmp tambin es una operacin binaria,  pero somete a 
los operadores una operacin aritmtica:  efecta  una substraccin 
sobre  el  primer  operando en la cantidad contenida en el segundo. 
Esta operacin no cambia el contenido de los operandos, pero activa 
o  no  alguna bandera dependiendo dependiendo  del  resultado.  Por 
supuesto,  si  el  contenido  de  ambos  operandos  es el mismo, se 
activar  la  bandera  de  cero  y  se  puede tomar una desicin al 
respecto:

	cmp	ax, note	; compara ax con el contenido en note
	je	dir2		; si son iguales, ir a dir2
	dec	ax		; si no son iguales decrementar AX
	jmp	dir3		; e ir a dir 3
dir2:	inc	ax		; si no eran iguales, incrementar AX
dir3:	mov	bx, ax		; poner en BX el valor en AX

Hemos incluido  una instruccin de control:  el salto incondicional 
"jmp". Es tambin un operador unario que pasa incondicionalmente el 
control a la direccin indicada  por el  operando.  La  instruccin 
tiene ciertas restricciones.  Para  los  procesadores anteriores al 
80386,  el salto condicional no puede superar el mbito de un salto 
corto (-128 a 127 bytes).

El salto  incondicional puede ser corto (-128 a 127 bytes), cercano 
(dentro de 32 KB), o lejana (a otro segmento).

Otros saltos condicionales sern revisados en su ocasin.


--------
Ejemplo
--------

Como una muestra del uso de los diversos direccionamientos, escribamos
el siguiente programa:

; --------------------------------------------------------
  TITLE TEST1.ASM: Programa para probar direccionamientos
; --------------------------------------------------------
	.model small
; --------------------------------------------------------
space	EQU	32
; --------------------------------------------------------
	.stack 32
; --------------------------------------------------------
	.data
string1	db	'Hola gente', 0
string2 db	'Programa_TEST1.ASM', 0
; --------------------------------------------------------
	.code
main	proc
_init:
	mov	ax, @data
	mov	ds, ax
	mov	si, 0
_print_string1:
		lea 	bx, string1
		mov	al, [bx][si]
		test	al, al
		jz	_print_string21

		mov	bx, 000Fh                                                   
		mov	ah, 0Eh                                                     
		int	10h
		inc	si
	jmp	_print_string1 

_print_string21:
	mov	cl, 4
	_next1:
		push	cx
		mov	al, space

		mov	bx, 000Fh                                                   
		mov	ah, 0Eh                                                     
		int	10h
	
		pop	cx
		dec	cx
	jne	_next1

_print_space:
	mov	si, 0
	_next2:
		mov	bx, offset string2
		mov	al, [bx+si+2]

		mov	bx, 000Fh
		mov	ah, 0Eh                                                     
		int	10h

		mov	ah, 10h
		int	16h

		inc	si
		cmp	si, 2
	jnz	_next2

	mov	al, space
	mov	bx, 000Fh                                                   
	mov	ah, 0Eh                                                     
	int	10h

_print_string22:
	lea	si, string2
	_next3:
		mov	al, [si]
		test	al, al
		jz	_end_

		mov	bx, 000Fh                                                   
		mov	ah, 0Eh                                                     
		int	10h

		mov	ah, 10h
		int	16h

		inc	si
	jmp	_next3
_end_:
	mov	ah, 10h
	int	16h

	mov	ax, 4C00h
	int	21h
main	endp
end	main
; ----------------------------------------------------------------------------
; Ensamblar con:
	TASM  TEST1
	TLINK TEST1
; ----------------------------------------------------------------------------
El  programa  es demasiado complejo para lo que hace:  desplegar la 
cadena string1, desplegar un espacio, y a medida que vamos pulsando 
una  tecla,  despliega  dos  caracteres  de string2 y al final toda 
string2.

Es  interesante notar cmo cambian los modos de direccionamiento en
cada despliegue.  Tambin hay varios detalles que debemos explicar,
adems de que tenemos la posibilidad y la necesidad de simplificarlo
y hacerlo ms claro: materia de nuestro siguiente captulo }:-)

-------------------------------------------------- TO BE CONTINUED ---------->


