Documentos de Académico
Documentos de Profesional
Documentos de Cultura
ASM7
ASM7
LENGUAJE ENSAMBLADOR
Elaborado por:
Lenguaje Ensamblador
.
LENGUAJE ENSAMBLADOR.
Temario del Curso.
I. Arquitectura del procesador
1.1 Introduccin
1.2 Importancia del Lenguaje ensamblador
1.3 Historia de los procesadores
1.4 Diagrama de bloques.
1.4.1 Descripcin de componentes
1.4.2 Funcionamiento interno
1.5 Capacidad de direccionamiento
1.6 Modos de direccionamiento
1.6.1 Implcito.
1.6.2 Inmediato
1.6.3 Registro
- Directo
- Relativo
- Base Indexado
- Base relativo
1.7 Formato de instrucciones
II. Programacin Bsica
2.1 Formato de un programa.
2.2 Instrucciones de transferencia de datos.
2.3 Instrucciones aritmticas.
2.4 Instrucciones lgicas.
2.5 Manipulacin de banderas.
2.6 Saltos
2.6.1 Incondicional
2.7.1 Condicional
2.7 Ciclos
2.8 Comparacin
2.9 Alto y no operacin (Hlt, Nop)
2.10 Rotacin y desplazamiento.
2.11 Directivas.
III. Programacin Modular
3.1 Definicin de rutinas.
3.2 Pase de parmetros.
3.3 Rutinas internas.
3.4 Rutinas externas.
IV. Programacin E/S
4.1 Definicin
4.2 Forma en que se ejecuta una interrupcin
4.3 Interrupciones.
4.3.1. BIOS
4.3.2. S.O.
II
Lenguaje Ensamblador
.
V. Macros
5.1
5.2
5.3
5.4
Definicin
Parmetros y etiquetas.
Ensamble de macros
Ventajas y desventajas.
Unidades de Aprendizaje.
UNIDAD I. Conocer los elementos arquitectnicos del procesador a utilizar, as como las
diferentes formas de acceso a los datos dentro de la computadora.
UNIDAD II. Conocer el formato de un programa escrito en lenguaje ensamblador y sus
instrucciones para aplicarlos en la elaboracin de programas.
- Desarrollo de programas en lenguaje ensamblador
UNIDAD III. Conocer y aplicar el uso de rutinas tanto internas como externas y las distintas
formas de llevar a cabo el pase de parmetros.
- Realizar programas utilizando modularidad.
UNIDAD IV. Conocer los mtodos de comunicacin con los dispositivos de E/S y la
aplicar en la elaboracin de programas.
- Desarrollar programas aplicando las instrucciones e interrupciones para entrada,
salida.
III
Lenguaje Ensamblador
.
Referencias Bibliogrficas.
1. Microcomputer systems: The Intel familly, architecture,
programming and design.
YU CHENG LIU, GLEN A. GIBSON
MC GRAW HILL
2. Programming the Intel 80386.
BUD E. SMITH, MARK JOHNSON
IBM BOOK
3. ASSEMBLY LANGUAJE AND SYSTEMS PROGRAMMING
FOR TEH IBM-PC AND COMPATIBLES
KAREN A. LEMONE
MAC MILLAN
4. THE 8086 BOOK
RECTOR, RUSSELL
OSBORNE-MC. GRAW HILL
5. 80386 ARCHITECTURE AND PROGRAMMING INCLUDING 80387
NUMERIC CO-PROCESSOR
TRIO, JEAN-MICHELL
MAC MILLAN
6. IBM PC ASSEMBLY LANGUAJE
A GUIDE FOR PROGRAMMING
LEO J, SCANLON
PRENTICE HALL
7. MACROASSEMBLER 6
FOR THE MS-DOS OPERATING SYSTEM
- PROGRAMMERS GUIDE
-MICROSOFT CODE VIEW A UTILITIES UP DATE
EDITOR MICROSOFT CORP.
8. INTRODUCCION AL 8086/8088
CRISTOPHER L. MORGAN, MICHELL W.
MC GRAW HILL
9. THE VISIBLE COMPUTER 8088 ASSEMBLY LANGUAJE
TEACHING SYSTEM
IBM PC.
10. PETER NORTON UNDER PC ASSEMBLY LANGUAJE
IV
Lenguaje Ensamblador
.
I. Introduccin.
La forma especfica y juego de instrucciones de cada ensamblador existente, depende
directamente de la arquitectura del microprocesador y componentes de la computadora para el
cual se haya realizado.
La primera computadora personal, lanzada por IBM, fue la IBM-PC. Basada en el
microprocesador Intel 8088. Su xito, popularidad y hoy en da, la forma ms accesible de
incursionar en l ambiente de las computadoras personales y de toda la familia que de sta se
origin, nos es posible que en base a ste modelo, podamos emprender a una excursin al
lenguaje ensamblador.
El concepto bsico y comportamiento de los dems ensambladores es algo similar, y
entendiendo uno ser ms fcil aprender los dems, ya que mucho del conocimiento que se
tenga, tambin es directamente proporcional al conocimiento de la forma en como las
computadoras realizan sus tareas. Esto es, si en las computadoras PC, se sabe que se cuenta con
algn dispositivo especifico para resolver alguna tarea, es posible que en otra arquitectura de
otra computadora se encuentre alguno similar con ms, o menos opciones.
An cuando parezca que las computadoras "entienden" lenguajes de alto nivel como
BASIC o Pascal, todas las computadoras corren actualmente en lenguaje mquina, los bytes
codificados que dirigen la unidad central de proceso de la computadora. Por esta razn cdigo
mquina es un mejor trmino que lenguaje de computadora de bajo nivel- el nico lenguaje que
la computadora conoce. Ya que el CPU de la computadora no puede ejecutar directamente las
sentencias de C y Pascal, los programas en stos y otros lenguajes de alto nivel deben de ser
compilados (traducidos) a cdigo mquina antes para que los programas puedan ser utilizados.
Similarmente, un programa escrito en un lenguaje intrprete como BASIC o LISP deben de ser
traducidos a cdigo mquina, aunque en estos casos, la traduccin sucede invisiblemente
mientras el programa se ejecuta, normalmente una sentencia a la vez.
Los programas de lenguaje ensamblador tambin deben de ser traducidos a cdigo mquina
por un programa llamado ensamblador.
No igual que las sentencias de C o Pascal, las cuales se pueden traducir a docenas de bytes de
cdigo mquina, las instrucciones de lenguaje ensamblador estn directamente relacionadas con
cdigos de maquina individuales - la mayor distincin entre los lenguajes de alto nivel y los
ensambladores. Todos los lenguajes tienen sus puntos a favor, pero solamente el lenguaje
ensamblador permite escribir programas directamente en el grupo de instrucciones indivisibles
del CPU.
Un poco de Historia.
Las computadoras IBM-PC, llegaron a revolucionar el mundo de las computadoras personales, a
la vez que se iniciaba una nueva generacin de chips procesadores de 16 bits. Fueron ingenios
ms grandes y poderosos, destinados a reemplazar o completar a las microcomputadoras de 8
bits de los aos 70's, que fueron las que comenzaron la revolucin de las microcomputadoras.
Con los procesadores de 8 bits se podan representar hasta 255 nmeros, mientras que a partir
de los procesadores de 16 bits, este nmero se incremento hasta 65535, un nmero 256 veces
mayor; as sucesivamente cada vez que se libera una nueva generacin dentro de la misma
familia, el numero capaz de representar contina en aumento, llegando en la actualidad a
manejar nmeros de 64 bits con direccionamientos de hasta 1.844674407371e+019.
La frmula para obtener el valor mximo de direccionamiento de un procesador es 2 n, donde n
es el numero de bits del procesador.
Es importante resaltar que los micorprocesadores INTEL de la familia 80X86 todava utilizan un
juego de instrucciones orientado a octetos (bytes);, esto es, que cada instruccin en lenguaje
Lenguaje Ensamblador
.
VI
Lenguaje Ensamblador
.
de
de
de
de
Alimentacin
Control
Direcciones
Datos.
VII
Lenguaje Ensamblador
.
Controlador
Controlador
Controlador
Controlador
Programable
Programable
Programable
Programable
Cada uno de los dispositivos externos est conectado a uno de estos controladores, que a su vez
se conectan al bus principal del sistema.
El plotter digital y el teclado comparten los 24 bits del controlador 8255.
Para la utilizacin de la pantalla grfica o monitor, se disponen de un gran nmero de tarjetas
con controladores grficas de distintas resoluciones grficas, colores y capacidades, segn
gustos y necesidades.
Observemos que, de hecho, la memoria RAM y ROM no son mas que otro dispositivo de los
procesadores. La ROM se utiliza para almacenar un pequeo programa de autocarga (bootstrap)
para la inicializacin del controlador de discos flexibles o duros. El programa carga el primer
sector del disco en memoria. Este primer sector contiene un programa que a su vez carga en
memoria el resto del sistema operativo; ste se encarga de inicializar los diversos controladores,
activndolos y dejndolos en disposicin de recibir rdenes.
VIII
Lenguaje Ensamblador
.
IX
Lenguaje Ensamblador
.
Unidades de Memoria.
Bit.
El bit es la unidad ms pequea de informacin. El trmino bit proviene de BInary digiT (dgito
binario). Un bit se almacena y transmite como seal que puede estar en dos estados; activa (on)
o inactiva (off). Puede usarse para almacenar variables lgicas o nmeros en aritmtica de base
2.
Cuarteto
Un cuarteto nibble son 4 bits, es decir, medio byte. Se utiliza fundamentalmente para
almacenar dgitos en cdigo BCD (decimal codificado en binario).
Octeto
Un octeto o byte son 8 bits, o 2 cuartetos. Puede almacenar un carcter (normalmente
codificado en ASCII), un nmero de 0 a 255, dos nmeros BCD u ocho indicadores de 1 bit.
Palabra.
Una palabra o word, consta de un nmero fijo de bits, aunque ste nmero vare de una
computadora a otra. Los microprocesadores de las generaciones actuales tienen palabras de 16
bits, 32 bits y 64 bits.
Para nuestro uso, trataremos a las palabras (words) como unidades de 16 bits, a unidades de
32 bits las denominaremos dobles palabras o double word, y al termino cuadruple palabra
(quarter word).
Estas unidades de memoria son tiles para almacenar nmeros ordinales y enteros.
Bloque.
Un Block es un grupo de celdas de memoria continua. No tiene tamao fijo, aunque en ciertos
contextos, como los discos, un bloque significa un tamao definido. Por ejemplo un sector
consiste de 512 bytes, dentro del sistema operativo MS-DOS.
Tipos de datos.
En stas unidades de memoria definidas anteriormente se almacenan datos. Cada tipo de dato
tiene un cierto formato o codificacin que requiere un cierto nmero de unidades de memoria.
Sin una descripcin del formato de memoria utilizado, los datos se convierten en algo ilegible y
sin sentido, sobre todo cuando utilizamos tipos de datos complicados como puede ser la
representacin de los nmeros de punto flotante.
Lgicos.
Un dato lgico es una cantidad que slo puede tomar uno de dos valores posibles: verdadero o
falso, 0 1, activo o inactivo, etc. Este tipo de dato tiene inters como indicadores condicionales
que definan bifurcaciones de programa dependiendo de su valor, o como indicadores de estado
para cierto dispositivo.
Lenguaje Ensamblador
.
Ordinales.
Son nmeros enteros sin signo, o valores de contadores comenzando en 0. Se almacenan en
la computadora en binario ocupando distintos tamaos. Si se utilizan ocho bits para guardarlos,
el ordinal puede tomar cualquier valor entre 0 y 255; en caso de utilizar 16 bits, el rango ordinal
vara de 0 a 65535; y con 32 o 64 bits, el ordinal puede tomar cualquier valor entre 0 y
4294967296, o 1.8x10
19
, respectivamente.
Enteros.
Son nmeros enteros con signo positivo o negativo (+ -). Los enteros se representan en forma
binaria de complemento a dos. En sta representacin, el bit de ms a la izquierda o ms
significativo (MSB) acta tanto como parte del nmero y como signo de ste. Una forma de
entender sta representacin es imaginarse que los nmeros estn distribuidos alrededor de una
rueda de dos maneras distintas. Supongamos que reservamos n bits para representar cada
n
nmero. Con n nmeros podemos representar ordinales entre 0 y 2 -1. Coloquemos estos
n
XI
Lenguaje Ensamblador
.
Punteros.
Las CPU Intel utilizan punteros para apuntar a direcciones fsicas en memorias. Se usan junto
con la segmentacin. Ene le caso del CPU 8086, una direccin fsica de memoria se guarda como
dos cantidades de 16 bits. Ambas cantidades se combinan de una forma especial, formando una
direccin real de 20 bits. Un puntero es una palabra doble que almacena esas dos cantidades, el
nmero de segmento y el desplazamiento.
XII
Lenguaje Ensamblador
.
En hexadecimal:
1
0
A
F
0
Direccin segmento
+
F
0
F
F
Direccin desplazamiento
------------------------------------------------------------1
F
B
E
F
Direccin de 20 bits
Es importante tener en mente que el enlazador LINK es quien define las direcciones de los
segmentos. As mismo, no todas las combinaciones de estas direcciones no son permisibles. Por
ejemplo, la siguiente combinacin no es vlida.
F
F
F
F
0
Direccin segmento
+
0
0
1
0
Direccin desplazamiento
------------------------------------------------------------NO
DEFINIDO
Direccin de 20 bits
En el ejemplo anterior no es posible representar la direccin generada de 20 bits, porque excede
el rango de 1 MegaByte. La notacin ms empleada para indicar la direccin de un par
segmento-desplazamiento consiste en separar con dos puntos los valores en hexadecimal, la
direccin del registro segmento se especifica primero. Para el ejemplo anterior, la direccin se
indica de manera convencional como:
10AF:F0FF
El programador de ensamblador, debe de familiarizarse bien con sta notacin, ya que de
sta forma los programas depuradores o DEBUG, arrojan su informacin.
Direccin
Lgica
0
1
2
3
0
1
2
3
0
1
2
3
0
1
2
3
Memoria Baja
Segmento
Segmento
Segmento
Segmento
Direccin
Fsica
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
XIII
Lenguaje Ensamblador
.
15
15
IP
CS
DS
SS
ES
AX
BX
AH
BH
AL
CX
DX
CH
CL
DL
BL
DH
Registros de Direcciones
de Segmentos
15
O D I T S Z
15
SP
BP
SI
DI
Registro de Bandeas
Registros de Direcciones
de Datos
Los mismos registros estn disponibles en todos los modelos 80X86. Aunque el 386 tiene
registros de longitud mayor y otros adicionales, si nos enfocamos en trabajar en los registros del
8086, se podra asegurar que nuestros programas corrern en todas las PCs.
Los registros estn agrupados en cinco categoras:
Todos los registros del 8086 tienen 16 bits de longitud. En adicin, los cuatro registros de
propsito general - ax, bx, cx, y dx - estn subdivididos en dos mitades, alta y baja (High, Low) de
8 bits. El registro ax, por ejemplo est compuesto de dos partes de 8 bits, ah y al. Este arreglo
flexible nos permite operar directamente trabajar con los 16 bits completos o trabajar
separadamente con las dos mitades de registros de 8 bits.
Hay que tener siempre en cuenta que si se modifica ax se modificar tambin las dos mitades
de registro de 8 bits. Al igual, cambiar el valor en cl, cambia tambin su valor en cx.
XIV
Lenguaje Ensamblador
.
XV
Lenguaje Ensamblador
.
La bandera de sobreflujo overflow flag indica si el resultado de una adicin con signo no puede
ser correctamente representada dentro de un cierto nmero de bits. Otras instrucciones pueden
tomar acciones en base a los estados de un bit de bandera.
Smbol
o
of
df
if
tf
sf
zf
af
pf
cf
Nombre completo
Overflow flag, Bandera de sobreflujo
Direction flag, bandera de direccin
Interrupt
enable
flag,
bandera
interrupciones
Trap flag
Sign flag, bandera de signo
Zero flag, bandera de cero.
Auxiliar flag, Bandera Auxiliar
Parity flag, Bandera de paridad.
Carry Flag, Bandera de acarreo
de
habilitacin
de
XVI
Lenguaje Ensamblador
.
XVII
Lenguaje Ensamblador
.
XVIII
Lenguaje Ensamblador
.
Modelos de Memoria
Nombre
tiny
small
medium
compact
large
huge
tpascal
Descripcin
Cdigo, Datos y Stack contenidos en un segmento de 64K. Llamada a subrutinas
y transferencias de datos son cercanas (near). Utilizado solo para programas
*.COM
Cdigo y Datos en segmentos separados de 64K. Llamada a subrutinas y
transferencias de datos son cercanas (near). Utilizada en programas .EXE de
tamao small a medium. La mejor opcin para programas exclusivamente en
lenguaje ensamblador
Tamao de cdigo ilimitado. Datos limitado a un segmento de 64K. Las llamadas
a subrutinas son de tipo far (lejanas); referencias a datos son de tipo near
(cercanas).
Tamao de cdigo limitado a un segmento de 64k. Datos ilimitado. Las llamadas
a subrutinas son de tipo near (cercanas); referencias a datos son de tipo far
(cercanas). Utilizada por programas de tamao medium a large con muchas
variables o muy largas.
Tamaos de Cdigo y Datos ilimitados. Las llamadas a subrutinas y referencias
de datos son de tipo far. Utilizadas para requerimientos de almacenaje de
programas y datos grandes. Tan grandes que las variables no excedan 64K.
Tamaos de Cdigo y Datos ilimitados. Las llamadas a subrutinas y referencias
de datos son de tipo far. Utilizadas por programas muy grandes donde una o
ms variables exceden los 64K.
Ensambla con segmentos de Turbo Pascal- similar al modelo small, pero con
mltiples segmentos de cdigo. No utilizado normalmente en la programacin
exclusiva en lenguaje ensamblador.
La directiva STACK reserva espacio para el stack del programa, un rea de memoria que guarda
dos tipos de datos: valores temporales guardados o pasados por subrutinas y las direcciones a
las cuales las rutinas regresaran el control. Los stacks entran en juego durante las interrupciones.
Manipular el stack es una importante tcnica de la programacin en lenguaje ensamblador. El
valor despus de la directiva STACK indica a l ensamblador cuantos bytes reserve para el
segmento Stack. La mayora de los programas requieren un stack pequeo, y cualquier programa
de los ms largos raramente requieren mas de 8K.
Igualdades, o asociaciones.
Despus de la cabecera del programa vienen varias constantes y declaraciones de variables. En
lenguaje ensamblador, los valores constantes son conocidos como igualdades o asociaciones,
refirindose a la directiva EQU, que asocia valores con identificadores tales como ValorMax y
DireccPuerto. Turbo ensamblador permite utilizar EQU, o un signo de igual (=), solamente para
valores numricos.
Utilizar igualdades de identificadores en lugar de nmero mgicos como 0100h y 0B800h nos
deja referirnos a expresiones, cadenas y otros valores por nombre, haciendo al programa fcil de
leer y modificar. (Los valores literales son mgicos porque es la manera en que pueden ocultar
secretos del programa). A continuacin se presentan unos cuantos ejemplos de asociaciones:
XIX
Lenguaje Ensamblador
.
Contador
Elemento
Tamanio
Texto
Tamanio
EQU
10
EQU
5
= Contador * Elemento
EQU Una pequea constante de cadena
= 0
=
=
=
66
100
LineasPorPag * NumPaginas
LineasPorPag * NumPaginas
XX
Lenguaje Ensamblador
.
25
80
0800h
XXI
Lenguaje Ensamblador
.
Los smbolos asociados con variables - numRen, numCol, y baseVideo en el ejemplo anterior son llamadas etiquetas. Una etiqueta apunta al elemento que est etiquetado- en este caso el
espacio de memoria reservado para valores del programa. Los programas pueden hacer
referencia a ste espacio utilizando una etiqueta como apuntador a el valor en memoria. En el
programa ensamblado, las etiquetas son traducidas a direcciones de memoria donde las
variables son almacenadas, un proceso que permite direccionar memoria por nombres que se
inventen mas que literalmente por su direccin de memoria.
Las variables son garanta que siguen una de otra dentro del segmento de datos- conocimiento
que se puede utilizar para realizar varios trucos. Por ejemplo, estas declaraciones:
aTom
nToz
DATASEG
db
'ABCDEFGHIJKLM'
db
'NOPQRSTUVWXYZ'
Como se aprecia, se crearon dos cadenas de caracteres etiquetadas con aTom y aToz. En
memoria, los caracteres a hasta z, son almacenados consecutivamente, creando una cadena
conteniendo las letras del alfabeto. La etiqueta nToz simplemente apunta a la mitad de la
cadena- estas no son dos realmente dos entidades de memoria.
Se puede pensar que, Por que, si DB quiere decir "definir byte", que est haciendo
declarando cadenas de caracteres?, buena pregunta, DB tiene la habilidad especial de reservar
espacio para valores multi-byte, desde 1 hasta tantos bytes como sean necesarios. Una cadena
est compuesta de caracteres individuales ASCII, cada uno ocupando un byte; por lo tanto, DB es
una simple herramienta del lenguaje ensamblador para declarar cadenas, las cuales, despus de
todo, son meramente series de valores byte ASCII almacenados consecutivamente en memoria.
Se puede utilizar DB para declarar caracteres individuales y valores byte, separados por comas:
DATASEG
dieznumeros
laHora
laFecha
db
db
db
1,2,3,4,5,6,7,8,9,10
9,0
; 9:00
15,12,93 ; 15/12/1993
Tambin se pueden combinar caracteres y valores byte, creando a una cadena de doble linea
con los cdigos ASCII de retorno de carro y salto de linea unidas en una sola declaracin.
combo
db
XXII
Lenguaje Ensamblador
.
Despus del segmento de datos viene el cuerpo del programa, tambin conocido como
segmento de cdigo- el pedazo de cdigo que contiene el cdigo de programa ensamblado.
Dentro de sta rea, las lineas de texto del lenguaje ensamblador son a su vez divididas en
cuatro columnas: etiquetas, mnemnicos, operandos y comentarios. Cada columna tiene una
funcin importante. En el texto del programa, por ejemplo, el monto de espacio entre columnas
no es importante. La mayora de las personas alinean las columnas simplemente presionando la
tecla TAB una o dos veces en su editor de preferencia.
Etiqueta
Mnemnico
Operando
Comentario
---------------------------------------------------------------------------------DATASEG
codSalida
db
0
; Una variable byte
CODESEG
Inicio:
mov
ax,@data
; Inicializa la direccin del segmento
mov
ds,ax
; de datos
jmp
Fin
; Salta a la etiqueta Fin
mov
cx, 10
; Esta linea es saltada
Fin:
mov
ah,04Ch
; Funcin DOS: Salida del programa
mov
al, [codSalida]
; Retorna el valor de cdigo de salida
int
21h
; Llama a DOS, termina el programa.
END
Inicio
; Fin del Programa.
Primeramente dentro del Segmento de Datos se declara una variable a utilizar dentro del
segmento de cdigo, la variable tipo byte es etiquetada como codSalida.
Despus de la directiva CODESEG, estn varias lineas divididas en etiquetas, mnemnicos,
operandos y comentarios. En la primer columna hay dos etiquetas Inicio: y Fin:. Las etiquetas
marcan lugares en un programa a los cuales otras instrucciones y directivas hacen referencia.
Las lineas que no necesitan etiquetas tienen espacios en sta columna. En el segmento de
cdigo, una etiqueta siempre termina con dos puntos (:). En el segmento de datos, una etiqueta
no debe terminar con dos puntos (:).
En la segunda columna estn los mnemnicos, literalmente "frmulas para recordar cosas".
Cada mnemnico en la segunda columna hace referencia a una instruccin de cdigo mquina.
Algunos son fciles de recordar- mov para Mover, jmp para Saltar, inc para Incrementar, etc.-,
otros no lo son tanto - jcxz salta si cx es igual con 0. Como se puede observar el lenguaje
ensamblador es abreviado al extremo. Tomara largo tiempo y paciencia aprender cada
mnemnico y su significado.
La tercer columna contiene los operandos - los valores con los cuales opera la instruccin
mnemnico que antecede. Unas cuantas instrucciones requieren de dos operandos, otras solo
requieren de uno. Ninguna instruccin del 80X86 requiere de tres operandos. El primer operando
es llamado normalmente destino. El segundo operando es llamado fuente.
La cuarta y ltima columna es siempre opcional y, si es incluida, debe iniciar con un punto y
coma (;), Turbo Assembler ignora todo desde el punto y coma hasta el final de la linea, dando
lugar para escribir un corto comentario, identificando secciones del programa y describiendo
secciones complicadas.
XXIII
Lenguaje Ensamblador
.
La parte final de un programa en ensamblador es el cierre, una simple linea que informa al Turbo
Assembler que ha alcanzado el fin del programa. Hay una sola directiva en el cierre: END. Un
cierre tpico de un programa es:
END
Inicio
La directiva END marca el fin del texto de cdigo fuente del programa. El Ensamblador ignora
cualquier linea escrita por debajo de sta. A la derecha de END, se debe especificar la etiqueta
donde se desea que el programa comience a ejecutar. Normalmente, esta etiqueta puede ser la
misma que la etiqueta que precede la primer instruccin siguiente a la directiva CODESEG. Se
puede iniciar el programa en cualquier parte, aunque no existe alguna razn para realizar esto.
;-------
db
Inicio:
;----- Insertar aqu el programa, llamadas a subrutinas, etc.
Fin:
mov
mov
int
END
ah, 04Ch
al,[codSalida]
21h
Inicio
;
;
;
;
XXIV
Lenguaje Ensamblador
.
small
256
;-------
;-------
db
ax,@data
ds,ax
ah, 04Ch
al,[codSalida]
21h
Inicio
;
;
;
;
XXV
Lenguaje Ensamblador
.
Instrucciones
Instrucciones
Instrucciones
Instrucciones
Instrucciones
Instrucciones
de Transferencia de Datos.
Aritmticas
Lgicas.
de Control de Flujo
de Control del Procesador
de Cadena
XXVI
Lenguaje Ensamblador
.
[nivel]<--- dl
Con los parntesis, se sabe que el valor de dl se mueve a la localidad en la cual nivel apunta.
Moviendo datos de sta manera - copiando el valor de un registro a otro y transferir datos desde
un registro a una localidad en memoria- es una de las operaciones ms comunes en
programacin de lenguaje ensamblador. Solo una cosa no puede hacer mov, lo cual es transferir
datos directamente entre dos localidades de memoria. Los siguiente no es vlido:
mov [contador,[maximo]; ???
Para mover el valor almacenado en maximo en la localidad direccionada por contador , requiere
de dos pasos, utilizando un registro como un auxiliar de almacenamiento intermedio.
mov ax, [maximo]; ax <-- [maximo]Error: Reference source not found
mov [contador]Error: Reference source not found, ax ; [contador]<--- ax
XXVII
Lenguaje Ensamblador
.
DB
DB
0
99
CODESEG
Inicio:
mov
ax, @data
mov
ds, ax
mov
ax,1
mov
bx,2
mov
cx,3
mov
dx,4
mov
ah,[datoX]
mov
si,offset [datoX]
Fin:
mov
ah, 04Ch
mov
al, [codSalida]
int
21h
END
Inicio
; variable de un byte
; Inicializa la direccin
; del segmento de datos
; Mueve datos inmediatos en registros
XXVIII
Lenguaje Ensamblador
.
El Stack es un segmento especial de memoria que opera en conjuncin con varias instrucciones
del 8086. Como con todos los segmentos, la localizacin del stack y su tamao (hasta 64K)
dependen del programador determinarlo. En los programas de lenguaje ensamblador, la forma
ms fcil de crear un stack es usar la directiva STACK. Un stack tiene tres propsitos principales:
-
0000
0002
0004
0006
ss:sp 0008
000A
ss:sp
000C
0F0
Stack
0:
200
100
3
ss:sp2
1
XXIX
Lenguaje Ensamblador
.
ax,100
ax
bx, 200
bx
; sp2
; sp3
ax
bx
cx
cx
bx
ax
En ste ejemplo, los registros ax, bx y cx, son posiblemente utilizados; por lo tanto, stos
registros son almacenados en el stack para preservar los valores de los registros. Por ltimo, los
valores son retirados (pop) del stack en orden inverso, restaurando los valores originales de los
registros y manteniendo el stack en sincrona.
XXX
Lenguaje Ensamblador
.
Instrucciones Aritmticas
Las mayora de las computadoras son grandiosas para las matemticas, esto viene a sorprender
que el lenguaje ensamblador solo tiene unos operadores matemticos relativamente primitivos.
No hay smbolos de exponenciacin, no hay punto flotante, no hay raz cuadradas, y no existen
funciones SENO y COSENO dentro del grupo de instrucciones del 8086. Las instrucciones
Matemticas en lenguaje ensamblador estn restringidas a sumar, multiplicar, dividir y restar
valores enteros con signo o sin signo.
Instrucciones
Generales
Descripcin
Mnemnico/Operand
o
Instrucciones de Adicin
aaa
Ajuste ASCII para adicin
adc destino, fuente
Suma con acarreo
add destino, fuente
Suma bytes o palabras
daa
Ajuste decimal para adicin
inc destino
Incremento
Instrucciones de Substraccin
aas
Ajuste ASCII para substraccin
cmp destino, fuente
Compara
das
Ajuste decimal para substraccin
dec destino
Decrementa byte o palabra
neg destino
Negar (complemento a dos)
sbb destino, fuente
Substrae
sub destino, fuente
Substrae
Instrucciones de Multiplicacin
aam
Ajuste ASCII para multiplicacin
imul fuente
Multiplicacin con enteros
mul fuente
Multiplicar
Instrucciones de Divisin
aad
Ajuste ASCII para divisin
cbw
Convierte bytes a palabras
cwd
Convierte palabras a dobles palabras
div fuente
Divide
idiv fuente
Divisin de Enteros
Existen dos formas de incrementar el poder matemtico del lenguaje ensamblador. Primero, se
puede comprar )o escribir) un paquete de funciones matemticas con rutinas que implementan
las funciones matemticas de alto nivel que se necesitan. Otra solucin es comprar un chip
coprocesador matemtico, aunque esto puede ser muy caro. Como una tercera opcin , y
probablemente la mejor, es utilizar un lenguaje de alto nivel como Pascal o C para codificar las
expresiones de punto flotante. Estos lenguajes vienen con un detector automtico de presencia
de coprocesador matemtico o cambiar a un software emulador para sistemas que carezcan del
chip opcional. Despus de escribir el programa, se puede combinar el cdigo compilado de alto
nivel, con nuestro programa en lenguaje ensamblador. Ya que el coprocesador matemtico tiene
requerimientos estrictos acerca de los datos y formatos de instrucciones, la mayora de los
compiladores generan cdigo mquina optimizado, y hay poca ventaja en escribir expresiones de
punto flotante directamente en lenguaje ensamblador.
Pero no tome esto como una pronunciada negativa en matemticas del lenguaje ensamblador.
An sin una librera matemtica o coprocesador, se pueden utilizar plenamente instrucciones de
enteros.
XXXI
Lenguaje Ensamblador
.
Por ejemplo, no se necesitan nmeros de punto flotante para totalizar los bytes en un directorio
de un disco o contar el nmero de palabras en un archivo de texto. Para stas y otras
operaciones, la matemtica entera es ms que adecuada. En lenguaje ensamblador puro, tales
trabajos frecuentemente trabajan ms rpidamente que cdigo equivalente de lenguajes de alto
nivel.
Ejemplo:
%TITLE Demostracin de ADD,SUB,INC,DEC
IDEAL
DOSSEG
MODEL small
STACK 256
DATASEG
codSalida
contador
DB
DW
0
1
CODESEG
Inicio:
mov
ax, @data
mov
ds, ax
; Inicializa la direccin
; del segmento de datos
mov
mov
add
ax,4
bx,2
ax,bx
; ax<-ax+bx
mov
add
cx,8
cx,[contador]
; cx<-cx+[contador]
add
[contador],cx
; [contador]<-[contador]+cx
inc
dec
inc
dec
[contador]
[contador]
ax
cx
;
;
;
;
mov
mov
int
ah, 04Ch
al, [codSalida]
21h
END
Inicio
[contador]<-[contador]+1
[contador]<-[contador]-1
ax<-ax+1
cx<-cx-1
Fin:
XXXII
Lenguaje Ensamblador
.
Ejemplo:
%TITLE Demostracin de MUL,DIV,IMUL,IDIV
IDEAL
DOSSEG
MODEL small
STACK 256
DATASEG
codSalida
opByte
opWord
ByteFuente
WordFuente
DB
DB
DW
DB
DW
0
8
100
64
4000
CODESEG
Inicio:
mov
mov
ax, @data
ds, ax
; Inicializa la direccin
; del segmento de datos
mov
mul
al,[opByte]
[ByteFuente]
; ax<- al * [ByteFuente]
mov
mul
ax,[opWord]
[WordFuente]
; ax,dx<- ax * [WordFuente]
mov
mul
ax,[opWord]
ax
; ax,dx<- ax * ax
mov
div
ax,[opWord]
[ByteFuente]
mov
mov
div
ax,[opWord]
dx,0
[WordFuente]
mov
mov
int
ah, 04Ch
al, [codSalida]
21h
END
Inicio
Fin:
XXXIII
Lenguaje Ensamblador
.
Instrucciones Lgicas.
Las instrucciones lgicas estn agrupadas en dos subdivisiones: lgicas e instrucciones de
rotacin/corrimiento. Las instrucciones lgicas combinan bytes y palabras con AND, OR, y otras
operaciones lgicas. Las Instrucciones de rotacin/corrimiento, realizan corrimientos y rotaciones
de bits en bytes y palabras.
Instrucciones Lgicas
Mnemnico/Operand Descripcin
o
Instrucciones Lgicas
and destino, fuente
AND lgico
not destino
NOT lgico, complemento a 1
or destino, fuente
OR lgico
test destino, fuente
Prueba bits
xor destino, fuente
OR Exclusivo lgico
Instrucciones de Corrimiento/Rotacin
rcl destino, contador
Rota hacia la izquierda con acarreo
rcr destino, contador
Rota hacia la derecha con acarreo
rol destino, contador
Rota hacia la izquierda
ror destino, contador
Rota hacia la derecha
sar destino, contador
Corrimiento aritmtico a la derecha
shl/sal
destino, Corrimiento a la izquierda/aritmtico
contador
shr destino, contador
Corrimiento a la derecha
La instruccin lgica mas simple not, cambia los bits en un byte o palabra de ceros a unos y los
unos a ceros. Esto es llamado complemento a uno, (sumar uno a este resultado forma el
complemento a dos, aunque es ms fcil usar neg para este propsito). Una forma de utilizar not
es para cambiar valores de verdadero y falso. Si un valor cero representa falso y un valor no cero
representa verdadero. La siguiente instruccin cambia el registro dh de verdadero a falso y lo
regresa a verdadero.
mov
not
not
dh,1
dh
dh
; Inicializa dh a verdadero
; cambia dh a "no verdadero", falso
; cambia dh a "no falso",
verdadero
XXXIV
Lenguaje Ensamblador
.
Ejemplo completo:
%TITLE Demostracin de AND,OR,XOR"
IDEAL
DOSSEG
MODEL small
STACK 256
DATASEG
codSalida
DB
WordFuente DW
WordMascara DW
0
0ABh
0CFh
CODESEG
Inicio:
mov
mov
ax, @data
ds, ax
; Inicializa la direccin
; del segmento de datos
mov
mov
mov
mov
ax,[WordFuente]
bx, ax
cx, ax
dx, ax
and
ax,[WordMascara]
or
bx,[WordMascara]
;bx<-bx OR mascara
xor
cx,[WordMascara]
xor
dx,dx
;dx<-0000
mov
mov
int
END
ah, 04Ch
al, [codSalida]
21h
Inicio
;
;
;
;
Fin:
Funcin
Retorno
Llama a
Fin del
XXXV
Lenguaje Ensamblador
.
La instruccin and es normalmente utilizada para verificar si uno o ms bits son igual a 1 en un
valor byte o word. Pro ejemplo, si se necesita determinar si el bit es 1, se puede utilizar la
mscara de 4:
0011 0111
0000 0100
--------------0000 0100
(Valor a probar)
(mscara AND)
(Resultado)
XXXVI
Lenguaje Ensamblador
.
Corrimientos sencillos
Rotaciones sencillas
Rotaciones atravs de cf
Corrimientos aritmticos
(shl, shr)
(rol, ror)
(rcl, rcr)
(sal, sar)
Msb
Lsb
cf
0
Corrimiento a la izquierda (shl/sal)
Msb
Lsb
cf
Msb
Lsb
cf
Rotar a la izquierda (rol)
Msb
Lsb
cf
XXXVII
Lenguaje Ensamblador
.
Msb
Lsb
cf
Rotar a la Izquierda con acarreo (rcl)
Msb
Lsb
cf
Msb
Lsb
cf
Para realizar corrimientos de bits por ms de un bit a la vez en el 8086 requiere de dos pasos:
primero cargar un valor contador en cl y entonces especificar cl como el segundo operando de la
instruccin de corrimiento:
mov
shl
cl,5
ax,cl
Se debe utilizar cl para esto - ningn otro registro trabajara como segundo operador. Se puede
tambin realizar corrimientos de bits dentro de localidades de memoria.
mov
shl
shl
shr
cl, 2
bh, cl
[segundos],1
[minutos], cl
;
;
;
;
Carga
Salta
Salta
Salta
count en cl.
en bh a la izquierda cl bits.
en [segundos] a la izquierda en 1.
en [minutos] a la derecha cl bits.
XXXVIII
Lenguaje Ensamblador
.
DB
DB
0
0AAh
CODESEG
Inicio:
mov
mov
ax, @data
ds, ax
; Inicializa la direccin
; del segmento de datos
shl
shr
rol
ror
rcl
rcr
sal
sar
[operando],1
[operando],1
[operando],1
[operando],1
[operando],1
[operando],1
[operando],1
[operando],1
;
;
;
;
;
;
;
;
mov
mov
int
ah, 04Ch
al, [codSalida]
21h
END
Inicio
Corrimiento a la izquierda
Corrimiento a la derecha
Rotar a la izquierda
Rotar a la derecha
Rotar a la izquierda con acarreo
Rotar a la derecha con acarreo
Corrimiento aritmtico a la izquierda
Corrimiento aritmtico a la derecha
Fin:
XXXIX
Lenguaje Ensamblador
.
La instruccin sar, opera identicamente a shr excepto que el MSB retiene su valor original.
Adicionalmente, el MSB es copiado al bit de la derecha. Esto es ms fcil de ver con ejemplos de
valores binarios:
10001000
11000100
11100010
11110001
11111000
Iniciando con el segundo valor, cada linea sucesiva muestra el resultado de aplicar sar al valor
de arriba. Los bits se corren hacia la derecha igual como lo realiza shr, pero el MSB retiene su
valor y es copiado al bit de la derecha. Como resultado, sar es til para dividir nmeros negativos
en complemento a dos por poderes de 2. Por ejemplo, expresado en hexadecimal, sucesivas
instrucciones sar producen sta secuencia:
8000 -32768
C000 -16384
E000
-8192
F000
-4096
F800
-2048
:
:
FFFE
-2
FFFF
-1
Instrucciones sar adicionales no tienen efecto en FFFF hexadecimal - no igual que idiv, el cual
es utilizado para dividir -1 por 2 lo cual resulta 0, como se podra esperar.
sar no tiene una contraparte hacia la izquierda. En su lugar, la instruccin shl se le otorg un
segundo mnemnico sal, maquillando la deficiencia. La razn de que un corrimiento aritmtico a
la izquierda no es diferente de un corrimiento sencillo a la izquierda, es evidente si examinamos
la secuencia en hexadecimal previa en reversa. Si trabajamos desde abajo, estos son los mismos
valores que podra producir el aplicar shl .
XL
Lenguaje Ensamblador
.
Instrucciones Lgicas
Mnemnico/Operand Descripcin
o
Instrucciones de transferencia incondicional
call destino
Llama un procedimiento
jmp destino
Salta incondicionalmente
ret valor
Retorna de un procedimiento
retn valor
Retorna de un procedimiento cercano
retf valor
Retorna de un procedimiento lejano
Instrucciones de transferencia condicional
ja/jnbe destino-corto
Salta si mayor/no menor o igual
jae/jnb destino-corto
Salta si mayor o igual/no menor
jb/jnae destino-corto
Salta si menor/no mayor o igual
jbe/jna destino-corto
Salta si menor o igual/no mayor
jc destino-corto
Salta si acarreo
je/jz destino-corto
Salta si igual/0
jg/jnle destino-corto
Salta si mayor/no menor o igual
jge/jnl destino-corto
Salta si mayor o igual/no menor
jl/jnge destino-corto
Salta si menor/no mayor o igual
jle/jng destino-corto
Salta si menor o igual/no mayor
jnc destino-corto
Salta si no acarreo
jne destino-corto
Salta si no igual/0
jno destino-corto
Salta si no hay sobreflujo
jnp/jpo destino-corto
Salta si NO paridad/paridad impar
jns destino-corto
Salta si no hay sobreflujo
jo destino-corto
Salta si sobreflujo
jp/jpe destino-corto
Salta si paridad / paridad par
js destino-corto
Salta si signo
Instrucciones de ciclos
jcxz destino-corto
Salta si cx es igual a 0
loop destino-corto
Ciclar mientras cx<>0
loope/loopz destino
Ciclar mientras igual/0
loopne/loopnz destino Ciclar mientras no igual/0
Instrucciones de Control de Interrupciones
int tipo interrupcin
Interrupcin
into
Interrupcin en sobreflujo
iret
Retorno de interrupcin
XLI
Lenguaje Ensamblador
.
Transferencias Incondicionales
Una transferencia incondicional cambia la direccin de la siguiente instruccin a ser
ejecutada. Una vez que el procesador realiza una transferencia incondicional, la instruccin
destino seria la siguiente a ejecutarse sin excepcin. Transferencias incondicionales cargan
nuevos valores de direcciones en el registro ip y en algunos casos, tambin dentro del registro
de segmento de cdigo cs. Juntos cs:ip especifican la direccin de la siguiente instruccin a
ejecutar. Cambiando uno o ambos registros cambia la direccin de sta instruccin, alterando el
flujo normal descendente del programa.
Llamando subrutinas.
Uno de los mecanismos del lenguaje ensamblador ms utilizados es la subrutina, una
coleccin de instrucciones relacionadas, normalmente realizando una operacin repetitiva. Una
subrutina puede desplegar una cadena de caracteres en la pantalla, sumar una serie de valores,
o inicializar un puerto de salida. Algunos programadores escriben largas subrutinas que realizan
mltiples trabajos en la teora que mltiples subrutinas pueden hacer que un programa rpido
corra lentamente. Se puede obtener un poquito de ms de velocidad combinando operaciones
dentro de una rutina masiva, pero se terminar con un programa difcil de mantener.
La mejor rutina hace uno y solo un trabajo. La mejor rutina es la ms corta posible y solo tan
larga como sea necesario. La mejor rutina puede ser listada en una o dos pginas de papel
impreso. La mejor rutina no comienza con cdigo, pero s con comentarios describiendo el
propsito de la rutina, resultados, entradas esperadas, y registros afectados. La mejor rutina
puede ser comprendida fuera del contexto por alguien quien no tenga idea que realiza el
programa completo.
XLII
Lenguaje Ensamblador
.
DB
DB
0
0AAh
CODESEG
Inicio:
mov
mov
ax, @data
ds, ax
; Inicializa la direccin
; del segmento de datos
mov
mov
mov
mov
call
call
call
al,1
;
bl,1
;
cl,1
;
dl,1
;
SumaRegistros
SumaRegistros
SumaRegistros
mov
mov
int
ah, 04Ch
al, [codSalida]
21h
Corrimiento a la izquierda
Corrimiento a la derecha
Rotar a la izquierda
Rotar a la derecha
;ax <- al+bl+cl+dl
;
;
Fin:
; Funcin de DOS: Salir del programa
; Retorno el Cdigo de salida
; Llama a DOS. Terminar programa
END
Inicio
; Fin del programa
;-----------------------------------------------------------------------;
SumaRegistros
al,bl,cl y dl
;-----------------------------------------------------------------------;
Entrada:
;
al,bl,cl,dl = Cuatro valores de 8 bits a Sumar
;
Salida:
;
ax = al + bl + cl + dl
;
Registros:
;
ax, bh, ch, dh cambian
;-----------------------------------------------------------------------PROC SumaRegistros
xor
ah,ah
xor
bh,bh
xor
ch,ch
xor
dh,dh
add
ax,bx
add
ax,cx
add
ax,dx
ret
ENDP SumaRegistros
END
Inicio
*Agregar sobre push y pop en subrutinas*
XLIII
Lenguaje Ensamblador
.
Saltos Incondicionales.
El 8086 tiene ms de una docena de instrucciones de saltos diferentes. Uno de estos, jmp, es
un salto incondicional; todos los dems son saltos condicionales. La diferencia entre los dos tipos
de saltos es muy importante:
-
Un salto incondicional siempre causa que el programa inicie corriendo en una nueva
direccin.
Un salto condicional causa que el programa inicie corriendo a una nueva direccin solo si
ciertas condiciones son satisfechas. De otra manera, el programa continua como si la
instruccin de salto condicional no existiese.
El jmp incondicional trabaja en forma idntica a call, excepto que la direccin de retorno
no es colocada en el stack. La instruccin jmp toma un solo parmetro: la etiqueta de la localidad
donde el programa transferir el control.
jmp
Salida
Saltos Condicionales.
La tabla siguiente lista las 18 instrucciones de salto condicional del 8086, muchas de las
cuales tienen dos mnemnicos representando la misma instruccin, por ejemplo, je/jz y
jg/jnle haciendo un total de 30 mnemnicos. Esto puede parecer un gran numero de saltos
condicionales que aprender, pero, como las conjugaciones de los verbos, las diferentes formas
son ms fciles de aprender si se separa la raz (siempre j para saltar), de las terminaciones (a,
nbe, e, z, etc.) Cada una de estas terminaciones representan una condicin nica. Una vez que
se memorizan sus significados, se tendrn menos problemas diferenciando los muchos tipos de
saltos condicionales.. En la tabla, las terminaciones a la derecha son negaciones de las
terminaciones a la izquierda. (Dos mnemnicos de salto condicional, jpe y jpo no tienen
contrapartes negativas).
Todos los saltos condicionales requieren de una direccin destino - una etiqueta marcando la
localizacin donde se desea el programa siga corriendo si la condicin especificada se cumple.
Por ejemplo, siguiendo a la comparacin de dos registros con cmp, se puede utilizar je (salta si
igual) para transferir el control a una localizacin si los valores de los registros son iguales. Para
demostrar esto, suponga la necesidad de una subrutina para retornar cx igual a 1 si ax = bx o 0
si ax<>bx.
PROC RegIguales
mov
cx,1
cmp
ax,bx
je
Continua
xor
cx,cx
Continua:
ret
ENDP RegIguales
;
;
;
;
Inicializa cx a 1.
ax es igual a bx ?
Salta si ax=bx
Sino, inicializa cx a 0000
; Retorna al llamador.
XLIV
Lenguaje Ensamblador
.
Significado
above
above or equal
below
below or equal
carry
equal
greater
grater or equal
less
less or equal
overflow
parity
parity even
parity odd
sign
zero
Traduccin
superior
superior o igual
inferior
inferior o igual
acarreo
igual
mayor
mayor o igual
menor
menor o igual
sobreflujo
paridad
paridad par
paridad impar
signo
cero
Trm.
na
nae
nb
nbe
nc
ne
ng
nge
nl
lne
no
np
not
not
not
not
not
not
not
not
not
not
not
not
Significado
above
above or equal
below
below or equal
carry
equal
greater
grater or equal
less
less or equal
overflow
parity
ns
nz
not sign
not zero
no
no
no
no
no
no
no
no
no
no
no
no
Traduccin
superior
superior o igual
inferior
inferior o igual
acarreo
igual
mayor
mayor o igual
menor
menor o igual
sobreflujo
paridad
no signo
no cero
ax,ax
inc
call
cmp
jne
:
ax
Imprime
ax,10
Contador
;
;
;
;
;
Contador:
ax<-ax+1
Llama a una subrutina
ax = 10 ?
Salta si ax <> 10
el programa continua
Restricciones.
Todos los saltos condicionales tienen una gran restriccin: pueden transferir control solo hacia
una distancia muy corta - exactamente 128 bytes hacia atrs (hacia direcciones bajas) o 127
bytes hacia adelante (hacia direcciones altas) desde el primer byte de la siguiente instruccin
inmediata al salto. No hay que preocuparse, el Ensamblador informar si se intenta realizar un
salto que sobrepase este rango.
Nota: Utilice saltos condicionales opuestos a los que normalmente utilizara si los
destinos estn dentro del rango. Entonces contine con un jmp incondicional a este
destino.
Para aprender ms acerca de como operan las instrucciones de salto condicional, trate de correr
algunos de los ejemplos en el Depurador. Ms que esto, piense lgicamente y no mecnicamente
como se acostumbra en los lenguajes estructurados. Desea saltar si el resultado es menor o
mayor (con signo), o si el resultado es superior o inferior (sin signo)?. Mantenga los saltos a
mnimas distancias posibles y evite utilizar muchos saltos.
XLV
Lenguaje Ensamblador
.
cmp
jne
mov
jmp
bx,5
Not5
ax,[contador5]
Continua
mov
ax,[Contador]
Not5:
Continua:
:
El fragmento anterior requiere de dos etiquetas y dos instrucciones de saltos solo para cargar ax
con un valor diferente dependiendo si bx es igual a 5. No trate de darle muchas vueltas al asunto.
Precarge ax con uno de los dos posibles resultados eliminando una etiqueta y el salto
incondicional.
mov
cmp
je
mov
ax,[contador5]
bx,5
Continua:
ax,[contador]
Continua:
:
Nos slo es ms corto y fcil de leer, el cdigo opera mas rpidamente cuando bx no es igual a
5. (Una instruccin jmp como se utiliza aqu, toma ms tiempo en ejecutarse que un mov entre un
registro y una localidad de memoria; por lo tanto, los dos movs no son una prdida como se
puede pensar en una lectura superficial).
XLVI
Lenguaje Ensamblador
.
PruebaBit3
test dl, 08h
jz
Exit
stc
; Prueba el bit 3
; Sale si el bit 3 = 0
; Establece la bandera de acarreo
Exit:
ENDP
ret
PruebaBit3
; Retorna al llamador
XLVII
Lenguaje Ensamblador
.
Instrucciones de Cadenas.
Las instrucciones de cadenas del 8086 son pequeos motores para procesar cualquier tiempo
de datos - no solamente cadenas. Recuerde que las cadenas en el leguaje ensamblador, son
secuencias de bytes que puede o no puede representar caracteres ASCII. Descartando sus
nombres sugestivos, las instrucciones de cadenas del 8086 no les importa lo que significan los
bytes. Las instrucciones de cadenas se dividen en tres grupos:
-
Instrucciones de Cadenas
Mnemnico/Operand Descripcin
o
Instrucciones de transferencia de cadenas
lods fuente
Carga cadenas de bytes o palabras
lodsb
Carga cadenas de bytes
lodsw
Carga cadenas de palabras
movs destino, fuente
Mueve cadenas de bytes o palabras
movsb
Mueve cadenas de bytes
movsw
Mueve cadenas de palabras
stos destino
Guarda cadenas de bytes o palabras
stosb
Guarda cadenas de bytes
stosw
Guarda cadenas de palabras
Instrucciones de inspeccin de cadena
cmps destino, fuente
Compara cadenas de bytes o palabras
cmpsb
Compara cadenas de bytes
cmpsw
Compara cadenas de palabras
scas destino
Busca cadenas de bytes o palabras
scasb
Busca cadenas de bytes
scasw
Busca cadenas de palabras
Instrucciones de Repeticin Prefijas
Rep
Repite
repe/repz
Repite mientras igual/0
repne/repnz
Repite mientras no igual/0
Las instrucciones de transferencia de cadenas mueven bytes y palabras desde memoria a
registros, desde registros a memoria; o directamente de memoria a memoria. Las instrucciones
de inspeccin de cadenas nos permiten comparar y buscar bytes o palabras buscando valores
especficos. Las Instrucciones de repeticin prefija, pueden ser combinadas como prefijos con
otras instrucciones de cadenas, creando comandos simples que repiten un nmero de veces o
ciclos hasta que se cumpla cierta condicin. Una instruccin de cadena con prefijo de repeticin,
puede llenar rpidamente miles de bytes con valores, copiar cadenas desde una localidad de
memoria a otra, y buscar valores en bloques de memoria largos.
Deseche los muchos mnemnicos de la tabla anterior, actualmente slo existen cinco
instrucciones de cadenas: lods, stos, movs, scas, y cmps. Las otras son nombres alternativos
cortos para estos mismos comandos. Como se puede apreciar en la tabla, los nombre cortos tales
como lodsb y cmpsw no requieren de operandos. Similarmente, solo hay dos prefijos de
repeticin: rep es idntico a repe y repz. Y repne y repnz representan el mismo prefijo. Los
nombres intercambiables son provistos meramente para ayudar a documentar lo que hace el
programa exactamente.
Registros ndices de Cadenas.
XLVIII
Lenguaje Ensamblador
.
Todas las instrucciones de cadenas utilizan registros especficos para realizar sus acciones. No
como otras instrucciones en que el programador decide cuales registros utilizar, las instrucciones
de cadenas son rgidas en este aspecto, siempre operan con la misma combinacin de registros
ds:si y es:di - los registros ndice de cadenas fuente y destino, los cuales especifican offsets en
los segmentos de datos y extra.
Nota: Si ds y es direccionan el mismo segmento de datos, como normalmente
sucede, no hay que concentrarse acerca del direccionar los segmentos de memoria
correctos durante las operaciones de cadenas. Cuando ds y es direccionan
segmentos diferentes, se debe ser cuidadoso en referenciar los segmentos
correctos. Tambin, el ndice destino di es siempre relativo al segmento
direccionado por es. El ndice fuente si es normalmente relativo al segmento
direccionado por ds, a menos que se especifique es explcitamente como en es:si.
Las cinco instrucciones cargan, mueven, comparan, y buscan bytes y palabras. Mientras
realizan estas tareas, cada instruccin de cadena tambin incrementa o decrementa los registros
que utilizan. Operaciones con byte restan o suman 1 a si o di (o ambos); operaciones con
palabras suman o restan 2. Por ejemplo, si si es igual a 0010h, entonces despus de una
operacin lodsw, si puede ser avanzado a 0012 ( o retardado a 000E, dependiendo de la
direccin de la operacin de cadena). Dado ste efecto sobre los registros ndice, adicionando un
prefijo de repeticin a una instruccin de cadena, los programas pueden procesar secuencias
completas de datos en un simple comando.
La bandera de direccin df especifica si las instrucciones cadena deben incrementar o
decrementar si y di. Si df = 1, entonces los ndices son decrementados hacia direcciones
bajas. Si df = 0, entonces los ndices son incrementados hacia direcciones altas. Utilizar cld para
limpiar df, automticamente incrementando si y di hacia direcciones altas. Utilizar std para
establecer df, automticamente decrementando si y di hacia direcciones bajas.
Nota: Aunque se puede establecer o limpiar df al inicio de un programa, df puede
ser cambiado por otra rutina, la forma ms segura siempre estableciendo o
limpiando la bandera de direccin inmediatamente antes de cualquier instruccin
de cadena. Esto toma un poco de tiempo y es una buena medicina preventiva
contra errores.
Cargando cadenas.
La instruccin lods carga datos direccionados por ds:si o es:si en al para operaciones
byte o dentro de ax para operaciones palabra. Despus de esto, si es incrementado o
decrementado, dependiendo del estado de la bandera de direccin df. Las operaciones byte
ajustan si por 1; operaciones palabra, por 2. Con esta instruccin, se puede construir un ciclo
simple para buscar por un valor byte:
cld
Repite:
lods
or
jne
; Auto-Incrementa si
[byte ptr ds:di]
al,al
Repite
XLIX
Lenguaje Ensamblador
.
Ya que lods normalmente opera sobre los valores direccionados por ds:si, Turbo Assembler
proporciona dos mnemnicos que no requieren operandos, lodsb y lodsw. La sb en este y en los
otros mnemnicos cortos de cadenas est por cadenas de bytes (string byte). La sw esta por
cadenas de palabras (string word). La tabla siguiente lista los formatos largos equivalentes a
todos los mnemnicos de formato corto.
cadena
DATASEG
db
'Esta es una cadena',0
CODESEG
mov
si, offset cadena ; Asigna la direccin de la cadena a si
lods [cadena]
; Obtiene el primer byte de la cadena
Lenguaje Ensamblador
.
; autoincrementa SI y DI
; Carga en el registro AX el word que apunte el registro SI
ax,0FFFFh ;
Salir
; Pone en la direccin apuntada por DI, el valor de AX
Repite
Moviendo cadenas
Utilice movs o los formatos cortos movsb y movsw para mover bytes y palabras entre dos
localidades de memoria. Ya que estas instrucciones no requieren de un registro intermedio para
almacenar a su manera, datos desde y hacia memoria, esta es la herramienta disponible ms
rpida para mover bloques de datos. Como con otras instrucciones de cadenas, se puede utilizar
el formato largo con operandos, o, como prefieren la mayora de los programadores, utilizar los
mnemnicos simples de formato corto.
Movsb mueve 1 byte de la localidad direccionada por ds:si a es:di a la localidad
direccionada por es:di, incrementando o decrementando ambos registros ndices por uno. Movsw
mueve una palabra entre dos localidades de memoria, incrementando o decrementando los
registros por 2. Aun cuando se pueden utilizar estas instrucciones individualmente para
transferir un byte o palabra - o construir ciclos para transferir valores sucesivos- normalmente se
adicionar un prefijo de repeticin como en el siguiente ejemplo.
cld
mov
rep
cx,100
movsb
;Auto incrementar
;Asignar contador a cx
;Mover 100 bytes
Estas tres instrucciones mueven 100 bytes de memoria iniciando en ds:si a la localidad
iniciando en es:di. El prefijo de repeticin rep ejecuta repetidamente movsb, decrementando cx
en 1 despus de cada repeticin, y terminando cuando cx es igual con 0. Se debe de utilizar cx
para ste propsito. Sin un prefijo de repeticin, se tendra que escribir las instrucciones de la
siguiente manera:
cld
mov
cx,100
; Auto incrementa
; Asigna contador a cx
Repite:
movsb
dec
cx
jnz
Repite
LI
Lenguaje Ensamblador
.
Llenando memoria
La instruccin stos realiza el llenado de memoria con un valor byte o palabra fcilmente.
Hay que ser muy cuidadoso con esto. Se puede borrar un segmento entero de memoria en un
flash. Por ejemplo, esto almacena el valor byte 0 en un bloque de memoria de 512 bytes,
iniciando en la etiqueta Buffer:
mov
mov
mov
xor
mov
cld
rep
LII
Lenguaje Ensamblador
.
cx,cx
Salto
stosb
Salto:
Esta secuencia salta a la etiqueta Salto si cx es 0. Solamente si cx no es 0 ejecuta la
instruccin rep stosb. Esto previene de repetir accidentalmente operaciones de cadenas 65,536
veces - a menos, por supuesto, que se desee realizar esto. En lugar de la secuencia anterior,
tambin se puede utilizar una instruccin especial de salto condicional, provista para ste
propsito:
jcxz
rep
Salto
stosb
Salto:
La instruccin jcxz realiza la misma funcin que las instrucciones or y jz en el ejemplo
previo.
Comparando cadenas
Para comparar dos cadenas, utilizar cmps o los formatos cortos cmpsb y cmpsw. La instruccin
compara dos bytes o palabras en es:di y ds:si o es:si. La comparacin con cmps substrae el
byte o palabra en es:di del byte o palabra en ds:si o es:si, afectando las banderas, pero no el
resultado - similarmente a como trabaja cmp. Despus de la comparacin, tanto si y di son
incrementados o decrementados por 1 para comparaciones byte y por 2 para comparaciones
palabra. Estas instrucciones casi siempre son precedidas de un prefijo de repeticin como en el
ejemplo siguiente:
cld
mov
mov
mov
repe
jb
ja
je
si,OFFSET s1
di,OFFSET s2
cx, longCadena
cmpsb
Menor
Mayor
Igual
;
;
;
;
;
;
;
;
Auto incrementar si y di
Direccionar la primera cadena con ds:si
Direccionar la segunda cadena con es:di
Asignar la longitud de la cadena a cx
Compara las dos cadenas
Salta si s1 < s2
Salta si s1 > s2
Salta si s1 = s2
Esta secuencia asume que la cadena s1 est almacenada en el segmento direccionado por ds y
que la cadena s2 esta almacenada en el segmento direccionado por es. Si ds = es, entonces las
dos cadenas pueden estar guardadas en el mismo segmento.
LIII
Lenguaje Ensamblador
.
ax, 5
; ax <- 5
El ensamblador genera una variante de cdigo mquina de la instruccin mov, que carga el valor
inmediato 5 dentro de ax. El 5 es almacenado directamente en el cdigo mquina ensamblado de
la instruccin mov. En la mayora de los casos, el datos inmediato es el nico operando o es el
segundo de dos operandos. (Una excepcin es out, la cual permite datos inmediatos como el
primero de dos operandos). Nunca se puede alterar el valor de un dato inmediato cuando el
programa se ejecuta.
Datos en Registros se refiere a datos guardados en los registros del procesador. El cdigo
mquina generado por el ensamblador para datos en registros, incluye valores apropiados
causando que la instruccin opere sobre los registros especificados, como en:
add
ax,bx
; ax<- ax+ bx
Datos en Memoria es el tercer tipo de referencia de datos, del cual hay muchas
variaciones. Para evitar confusin cuando se aprenden stas variantes, recordar que el punto
clave es ayudar al procesador a calcular un valor sin signo de 16 bits, llamado direccin efectiva,
o EA (effective address). La EA representa un desplazamiento iniciando desde la base del
segmento direccionado por uno de los cuatro registros de segmento: cs, ds, es y ss. Un
registro segmento y un desplazamiento forman una direccin lgica de 32 bits, la cual el 8086
traduce en una direccin fsica de 20 bits, para localizar cualquier byte en memoria.
No hay que preocuparse acerca de como calcular una direccin efectiva o formar la direccin
fsica de 20 bits, estos son trabajos del procesador. La responsabilidad del programador es
proporcionar al procesador los datos necesarios para calcular la direccin efectiva, localizando las
variables en memoria. Para realizar esto, se pueden utilizar uno de siete modos de memoria,
como se describen a continuacin.
LIV
Lenguaje Ensamblador
.
[Contador]
ch, [es:contador]
dh, [cs:ByteCodigo]
dh, [ss:ByteStack]
dh, [ds:ByteDato]
Siempre y cuando se declare una sobre-especificacin como parte de una referencia de dato,
una sobre-especificacin ocupa un byte de cdigo mquina y es insertado justo antes de la
LV
Lenguaje Ensamblador
.
En lugar de referir a variables en memoria por su nombre, se pueden utilizar uno de tres
registros como apuntador a datos en memoria: bx, si y di. Ya que un programa puede modificar
valores de registros para direccionar diferentes localidades de memoria, el direccionamiento
indirecto por registro permite a una instruccin operar en mltiples variables. Despus de cargar
una direccin de desplazamiento dentro de un registro apropiado, se puede hacer referencia a
datos almacenados en memoria con instrucciones tales como:
mov
dec
Los operadores WORD y BYTE son requeridos cuando el Turbo Assembler es incapaz de saber
cuando el registro direcciona a un byte o palabra en memoria. En la primer linea del ejemplo
anterior, el datos direccionado por bx es movido dentro del registro cx, por lo tanto el operador
WORD no es necesario ya que Turbo Assembler conoce el tamao de la referencia del dato por
contexto de la instruccin, no hay problema si se realiza esto. En la segunda linea el operador
BYTE debe ser incluido, ya que el ensamblador no tiene otra forma de saber si dec est
decrementando un byte o una palabra.
El Direccionamiento Indirecto por registro trabaja por default sobre el segmento direccionado
por ds. Como con el direccionamiento directo, se puede usar sobre-especificaciones para cambiar
a cualquiera de los otros tres segmentos.
add
dec
mov
[WORD es:bx],3
[BYTE ss:si]
cx, [cs:di]
LVI
Lenguaje Ensamblador
.
Direccionamiento Base
El direccionamiento Base emplea dos registros, bx y bp. Las referencias a bx son relativas al
segmento direccionado por ds. Las referencias a bp son relativas al segmento de stack ss y son
normalmente utilizados para leer y escribir valores almacenados en el stack. Se pueden utilizar
sobre-especificaciones de segmentos como los descritos previamente para referir datos en
cualquiera de los otros segmentos.
El direccionamiento base adiciona un valor de desplazamiento a la localidad direccionada por
bx o bp. Este desplazamiento es un valor con signo de 8 o 16 bits que representa un
desplazamiento adicional por arriba o por abajo del desplazamiento en el registro especificado.
Un uso tpico del direccionamiento base es localizar campos en una estructura de datos. Por
ejemplo:
mov
mov
[WORD bp + 2]
[BYTE bp - 8]
Direccionamiento Indexado.
El direccionamiento Indexado es idntico al direccionamiento base, excepto que si y di
almacenan las direcciones de desplazamiento, A menos que se sobre-especifique un segmento,
todas las referencias a direcciones indexadas son relativas al segmento de datos direccionado
por ds. Normalmente, el direccionamiento indexado es utilizado para accesar arreglos simples.
Por ejemplo, para incrementar el quinto byte de un arreglo de valores de 8 bits, se puede escribir.
inc
[BYTE si + 4]
LVII
Lenguaje Ensamblador
.
ax,
ax,
ax,
ax,
[bx
[bx
[bp
[bp
+
+
+
+
si]
di]
si]
di]
Turbo Assembler permite invertir el orden de los registros, por ejemplo, escribir [si + bx]
y [di + bp]. Pero estos no son modos de direccionamiento diferentes - solo diferentes formas de
referenciar lo mismo. Tambin se puede adicionar un valor de desplazamiento opcional para
cualquiera de las cuatro variaciones previas.
mov
mov
mov
mov
ax,
ax,
ax,
ax,
[bx
[bx
[bp
[bp
+
+
+
+
si
di
si
di
+
+
+
+
5]
5]
5]
5]
ax, [es:bx + si + 8]
ax, [cs:bp + di]
; Utilizar es en lugar de ds
; Utilizar cs en lugar de ss
Continua
5
ah,[cs:v1]
LVIII
Lenguaje Ensamblador
.
El cdigo anterior ilustra una forma de guardar datos dentro del segmento de cdigo - una
prctica inusual pero permisible. La instruccin jmp salta sobre la declaracin de una variable
byte v1. (Cuando se mezcla datos y cdigo, no se desea que accidentalmente se ejecuten las
variables como si estas fueran instrucciones.) La instruccin mov utiliza una sobre-especificacin
de segmento (cs:), para cargar el valor de v1 dentro de ah. La sobre-especificacin es requerida
dado que las referencia directas a datos normalmente las hace sobre el segmento de datos ds.
Aun cuando no se utilice explcitamente una sobre-especificacin, Turbo Assembler checa
su lista de variables, detecta que v1 es almacenado en el segmento de cdigo, y
automticamente inserta la sobre-especificacin requerida. En otros casos cuando Turbo
Assembler no conoce a cuales registros de segmento se refiere, se debe utilizar una sobreespecificacin explcita o decirle al ensamblador que va a hacer con la directiva ASSUME.
CODESEG
jmp
v1
db
Continua:
mov
mov
ASSUME
mov
Continua
5
ax,@code
es,ax
es:_TEXT
ah,[v1]
ah,[cs:v1]
Dado que v1 est almacenada en el segmento de cdigo, por lo tanto, tanto [es:v1] y [cs:v1]
localizan correctamente la misma variable. Todo lo que hace ASSUME es permitir al ensamblador
insertar una instruccin sobre-especificacin automticamente.
LIX
Lenguaje Ensamblador
.
Expresiones y Operadores
Expresiones en lenguaje ensamblador tienen un propsito: hacer que los programas sean ms
fciles de entender y , por lo tanto, fciles de modificar. Por ejemplo, se pueden tener varias
constantes, asociando valores opcionales con smbolos tales como:
TamReg
NumReg
EQU
EQU
10
25
dw
TamReg * NumReg
Cuando Turbo Assembler procesa sta directiva, multiplica TamReg por NumReg y guarda la
constante resultante (250) en la variable palabra TamBuffer. Es importante comprender que ste
calculo ocurre durante el ensamble - no cuando corre el programa. Todas las expresiones evalan
a constantes en lenguaje ensamblador. En lenguajes de alto nivel, expresiones tales como
(NumColumnas *16) son evaluadas en tiempo de ejecucin, posiblemente con un nuevo valor
para una variable llamada NumColumnas introducido por un usuario. En lenguaje ensamblador
las expresiones se reducen a valores constantes cuando se ensambla el texto del programa, no
cuando se ejecuta el programa. La diferencia puede ser confusa la primera vez, especialmente si
se est mas acostumbrado a la programacin de alto nivel que a la de bajo nivel.
La tabla a continuacin, lista expresiones operadores, las cuales se pueden utilizar para
calcular valores constantes de cualquier tipo imaginable.
Operador
()
*
/
+
.
:
?
[]
AND
BYTE
DUP
DWORD
EQ
FAR
FWORD
GE
GT
HIGH
LARGE
LE
LENGHT
LOW
LT
MASK
Descripcin
Parntesis
Multiplicacin
Divisin
Suma/suma unaria
Resta/resta unaria
Miembro de estructura
Sobre-especificacin, segmento
Dato sin inicializar
Referencia de memoria
AND lgico
Forzar a tamao byte
Duplicar variable
Forzar a Doble palabra
Igual
Apuntador a codigo lejano
Tamao de palabra lejana
Mayor o Igual
Mayor que
Retorna la parte alta
Forza desplazamiento de 32-bits
Menor o igual
Nmero de elementos
Parte baja
Menor o igual
Mascara de bits, Registro/campo
Operador
MOD
NE
NEAR
NOT
OFFSET
OR
PROC
PTR
PWORD
QWORD
SEG
SHL
SHORT
SHR
SIZE
SMALL
SYMTYPE
TBYTE
THIS
TYPE
UNKNOWN
WIDTH
WORD
XOR
Descripcin
Residuo de divisin
No igual
Apuntador a cdigo cercano
Complemento a 1
Direccin de desplazamiento
OR lgico
Apuntador a cdigo Near/Far
Tamao de expresin
Puntero lejano de 32 bits
Cuadruple palabra
Direccin de segmento
Corrimiento a la izquierda
Apuntador corto a cdigo.
Corrimiento a la derecha
Tamao de elemento
Desplazamiento de 16-bits
Tipo Simbolo
Tamao de diez bytes
Refiere al siguiente elemento
Typo de elemento
Remueve informacin de tipo
Bit de ancho de campo
Tamao palabra
OR exclusivo
No hay que confundir operadores tales como AND, OR, XOR y NOT con los mnemnicos del
mismo nombre en lenguaje ensamblador. Los mnemnicos de lenguaje ensamblador son
instrucciones que operan en tiempo de ejecucin.
LX
Lenguaje Ensamblador
.
Variables simples
En los ejemplos anteriores se crearon variables simples con las directivas db y dw. Estas
directivas pertenecen a una familia de instrucciones similares, todas con el mismo propsito
general: para definir (significando reservar) espacio para valores en memoria. Las directivas
difieren solo en cuanto espacio pueden definir y los tipos de valores iniciales que se pueden
especificar. La tabla a continuacin lista las siete de stas tiles directivas ordenadas de acuerdo
a mnimo de espacio que reserva cada una. Tambin se listan los ejemplos tpicos, aunque las
directivas no estn limitadas solamente a la utilizacin mostrada aqu. Se pueden escribir
cualquiera de estas directivas en maysculas o en minsculas.
Directiva
Significado
Db
Dw
Dd
Dp
Df
Dq
Dt
Define
Define
Define
Define
Define
Define
Define
Mnimo de
Bytes
1
2
4
6
6
8
10
Byte
palabra
doble palabra
puntero
puntero lejano
cuadruple palabra
diez bytes
Uso normal
Bytes, cadenas
Enteros
Enteros largos
Apuntadores de 32-bits
Apuntadores de 48-bits
Numeros Reales
Numeros BCD
Para crear grandes cantidades de espacio, se pueden unir varias db, dw u otras directivas de
memoria, o se puede utilizar el operador DUP, el cual es normalmente ms conveniente. DUP tiene
la siguiente forma:
[ETIQUETA]
directiva
contador
DUP (expresin,[expresin]..)
Para crear un espacio multibyte, iniciar con una etiqueta opcional y una directiva de definicin
de memoria. Siguiendo a este por un contador igual al nmero de veces que se quiere duplicar
una expresin, la cual debe estn entre parntesis. La palabra reservada DUP va entre el contador
y la expresin. Por ejemplo, cada una de stas directivas reservan un rea de memoria de 10
bytes, inicializando todos los diez bytes a 0:
Diez1
Diez2
dt
db
0
10 DUP(0)
Separando mltiples expresiones o valores constantes con comas duplica cada valor en turno,
incrementando el total de tamao de espacio reservado, por el numero de veces el numero de
elementos.
Veinte1
db
Tambin se pueden anidar expresiones DUP para crear buffers largos inicializados a valores
constantes. Por ejemplo, cada una de las siguientes directivas reservan una rea de 20 bytes con
todos los bytes iguales a 255.
Veinte2
Veinte3
db
db
LXI
Lenguaje Ensamblador
.
Estos mismos ejemplos trabajan con cualquiera de las directivas de definicin de memoria para
reservar diferentes montos de espacio. Normalmente se utilizar db y dw para enteros, cadenas y
variables byte, poniendo las otras directivas a trabajar solo para propsitos especiales. Pero se es
libre de utilizar stas directivas como mejor nos parezca. Para crear una variable de 20-bytes con
todos en 0, por ejemplo, se puede utilizar db como en el ejemplo anterior o dt como en este:
Veinte4
dt
De todas las directivas de definicin de memoria, solo db tiene la habilidad especial para
reservar espacio para cadenas de caracteres, almacenando un caracter ASCII por byte en
memoria. Aqu hay un ejemplo, terminando con un byte 0, una tpica construccin llamada
cadena ASCIIZ:
Cadena
db
Combinando la habilidad de db para las cadenas con el operador DUP es una herramienta til
para llena un buffer de memoria con texto que es fcil de localizar mediante un depurador.
Buffer
db
; 1024 bytes
DUP repite la cadena de 8 bytes entre parntesis 128 veces, reservando as un total de
1024 bytes.
Datos inicializados contra Datos Sin Inicializar
Cuando se sabe que el programa asignar nuevos valores a las variables, y por lo tanto no nos
preocupan los valores iniciales, se pueden definir variables sin inicializar- aquellas que no tienen
valores especficos cuando el programa se ejecuta. Para hacer esto, hay que usar el signo de
interrogacin (?) en lugar de la constante en la definicin de memoria:
algo
otro
valorx
db
dw
?
?
dt
Para crear grandes espacios de memoria sin inicializar, utilizar el signo de interrogacin dentro
de los parntesis de la expresin DUP, una tcnica til para crear grandes buffers tales como:
Buffer
db
La principal razn de crear datos sin inicializar es reducir el tamao del archivo de cdigo
ensamblado. En lugar de guardar bytes innecesarios en disco, el espacio sin inicializar es
reservado en tiempo de ejecucin. Para ste trabajo, se debe seguir una de estas dos reglas:
-
Colocar todas las variables sin inicializar al final de la declaracin del segmento de datos
O preceder las variables sin inicializar con la directiva UDATASEG.
LXII
Lenguaje Ensamblador
.
var1
var2
arreglo
var3
DATASEG
db
db
UDATASEG
db
DATASEG
db
1
2
1000 DUP(?)
3
Variables cadena
Mientras db puede crear variables de cadenas de caracteres, pero el lenguaje ensamblador no
tiene comandos de construccin de cadenas, para leer o escribir cadenas, eliminar caracteres,
comparar una cadena con otra. Hay que escribir programas que realicen tales operaciones. Antes
examinaremos unos cuantos formatos tpicos de cadenas. Probablemente el formato de cadenas
mas comn es el ASCII$ - una serie de caracteres ASCII terminando en un signo de pesos. Utilizar
db de sta manera para crear una cadena ASCII:
cadena
db
'Este es un mensaje','$'
El mayor problema al utilizar las cadenas ASCII$ es obvio, - no hay una forma fcil de desplegar
un signo de pesos. Tambin, es difcil leer caracteres del teclado o desde archivos de disco en
tales cadenas. Por estas razones. Hay quienes raramente utilizan las cadenas ASCII$, en su lugar
es preferible utilizar las cadenas ASCIIZ, cadenas con terminacin en un byte con valor 0 - el
mismo formato utilizado por los compiladores de C de alto nivel. Con cadenas ASCIIZ, se puede
crear un mensaje de error escribiendo:
ErrDisk
db
Las cadenas ASCIIZ pueden ser tan largas como se requiera - desde un caracter hasta miles. La
nica desventaja de las cadenas ASCIIZ, es que DOS no tiene rutinas estandard para leer o
escribir variables con ste formato.
Para todas las cadenas declaradas con db, se pueden encerrar caracteres tanto con apostrofes (')
o comillas ("), solo hay que iniciar y cerrar con el msmo smbolo.
Para incluir comillas dentro de una cadena, hay varias opciones. El mtodo ms fcil es
utilizando un tipo de simbolo, encerrando la cadena de caracteres conteniendo el otro tipo:
Ejemplo1
Ejemplo2
db
db
LXIII
Lenguaje Ensamblador
.
Etiquetas locales
Hasta ahora, los programas de ejemplo utilizan etiquetas dentro del segmento de cdigo como
Inicio: y Repite:. Tales etiquetas son globales para todo el programa que los declara. En otras
palabras, si se etiqueta una instruccin etiq1: al inicio del programa, esa etiqueta est
disponible para call, jmp y otras instrucciones en cualquier otra parte del cdigo. Un problema
con esto es que, constantemente hay que pensar en nuevos nombres para evitar conflictos con
etiquetas que ya se utilizaron. En saltos cortos, se presenta el mayor inconveniente:
cmp
je
add
ax, 9
Salto:
cx, 10
; ax = 9
; salta suma siguiente si ax = 9
; si no sumar 10 a cx
Salto:
Saltos cortos como je a la etiqueta Salto son muy comunes en la programacin en
lenguaje ensamblador. Un programa largo puede tener cientos o miles de saltos similares,
requiriendo que se inventen nuevos nombres para cada uno. Para reducir este problema, Turbo
Assembler nos permite crear variables locales, las cuales existen solamente en secciones de
cdigo que los necesita.
Una etiqueta local es idntica a cualquier otra etiqueta pero inicia con dos signos " @@",
Ejemplos de etiquetas locales incluyen nombre tales como @@10:, @@Aqui, @@Temp6, y @@x:. La
vida de una etiqueta local se extiende solamente hacia adelante o hacia atrs, de la siguiente
etiqueta no local. Ya que esto incluye etiquetas definidas en directivas PROC, si se encierran
procedimientos con PROC y ENDP, las etiquetas locales en subrutinas son visibles solamente
dentro del cdigo de la rutina. Entonces se puede reutilizar la misma etiqueta local en cualquier
parte sin conflicto. Un ejemplo ayuda a hacer esto ms claro:
jmp
Aqui
inc
cmp
jne
ax
ax,10
@@10
cmp
je
xor
ax, 20
@@10
cx,cx
@@10:
Aqui:
@@10:
El primer jmp salta a la etiqueta global Aqui:- se puede saltar a etiquetas globales desde
cualquier parte del programa. El siguiente jne salta a la etiqueta local @@10:. Pero, cual, si hay
dos?. La respuesta es , a la primer @@10:, la cual se extiende solamente hasta la etiqueta global
@@Aqui:. Consecuentemente, la instruccin jne puede "ver" solamente el primer @@10:. Por la
misma razn, la ltima instruccin je salta abajo hacia la segunda @@10: dado que la etiqueta
global Aqui: bloquea la visibilidad de la primer etiqueta local.
LXIV
Lenguaje Ensamblador
.
Etiquetas locales ahorran memoria, permitiendo a Turbo Assembler reusar RAM para otras
etiquetas locales. Las etiquetas globales son permanentemente almacenadas en memoria
durante el ensamble, aunque solamente se utilicen una vez. Las etiquetas locales son
liberadas cada vez que una nueva etiqueta no local es encontrada.
Las variables locales proveen claridad al programa. Por ejemplo, en una bsqueda rpida de
un programa, fcilmente se diferencian las etiquetas locales y las globales.
Las etiquetas ayudan a reducir errores haciendo mas difcil de escribir saltos de larga
distancia desde un lugar en el programa a otro. Si se encierran los procedimientos con
directivas PROC y ENDP, no se estar tentado a saltar a una etiqueta temporal en la seccin
media de una subrutina - un error de cdigo generalmente encontrado.
LXV
Lenguaje Ensamblador
.
Fecha
db
1
db
?
dw
1995
Fecha
Se puede insertar campos de cualquier tipo dentro de una estructura, utilizando los
mismos mtodos que se utilizan para declarar variables. Este ejemplo tiene tres campos: dia,
mes, y anio. El primero de dos campos son bytes, como el primero de estos valores inicializado a
1. El segundo campo tipo byte esta sin inicializar. El tercer campo es una palabra, inicializada a
1991. La identacin de cada campo es solamente por apariencia. Cuando se definen estructuras
tales como sta, hay que recordar estos puntos importantes:
-
Una estructura no es una variable. Una estructura es el esquema para una variable.
Las estructuras pueden ser declaradas en cualquier parte. La directiva STRUC no tiene que
estar declarada dentro del segmento de datos del programa, aunque esto es posible.
Una estructura le informa a Turbo Assembler acerca del diseo de variables que se planea
declarar posteriormente o que ya existe en memoria.
Aunque se utilicen directivas tales como db y dw para definir los tipos de campos de la
estructura, la estructura no reserva espacio en el segmento de datos o causa que cualquier
byte sea escrito en el programa final.
Declarando variables estructuradas
Para utilizar un diseo estructurado, se debe reservar espacio en memoria para los campos de
la estructura. El resultado es una variable que tiene el diseo de la estructura. Iniciando la
declaracin de cada una de stas variables con una etiqueta, seguida por el nombre de la
estructura, y terminando con una lista de valores predeterminados encerrados entre los smbolos
< >. Dejando el espacio vaco entre estos smbolos para utilizar los valores predeterminados ( si
los hay), definidos anteriormente en la definicin de la estructura. Retornando nuevamente con el
ejemplo de la estructura Fecha, en el segmento de datos del programa se puede declarar varias
variables fecha:
DATASEG
hoy
fecha <5,10,1995> ; 5-10-1995
navidad
fecha <24,12,>
; 24-12-1995
agosto
fecha <,8,>
; 1-8-1995
LXVI
Lenguaje Ensamblador
.
La variable fecha hoy, reemplaza los tres valores predeterminados - dia, mes y anio- con
5, 10 y 1995. La segunda variable navidad reemplaza dos de los valores predeterminados - dia
y mes- con 24 y 12. El tercer valor faltante de declarar asume el valor predeterminado del diseo
de la estructura, el cual es 1995. La tercer variable agosto especifica un nuevo valor para mes
mientras se utilizan los valores por default para los dems. La primer coma es necesaria para
"obtener" el segundo campo de la estructura. La segunda coma no es necesaria.
%TITLE Demostracin de estructuras"
IDEAL
DOSSEG
MODEL small
STACK 256
STRUC
Fecha
db
1
db
?
dw
1995
Fecha
dia
mes
anio
ENDS
STRUC
CiudadEstado
db
"####################",0; 20 caracteres
db
"###",0
; 3 caracteres
CiudadEstado
ciudad
estado
ENDS
DATASEG
codSalida
DB
hoy
cumpleanios
AnioNuevo
NuevoSiglo
Fecha
Fecha
Fecha
Fecha
direccion
Veracruz
Guadalajara
Colima
EsteEstado
EstaCiudad
CiudadEstado
CiudadEstado
CiudadEstado
CiudadEstado
CiudadEstado
CiudadEstado
<>
<28,10,1995>
<1,1,1996>
<1,1,2000>
<>
<'Veracruz','VER'>
<'Guadalajara','JAL'>
<'Colima','COL'>
<,'VER'>
<'Veracruz',>
CODESEG
Inicio:
mov
mov
ax,@data
ds,ax
mov
mov
int
ah, 04Ch
al, [codSalida]
21h
END
Inicio
Fin:
LXVII
Lenguaje Ensamblador
.
[hoy.dia], 5
; Cambia dia a 5.
ax, [hoy.anio]
; Obtiene el ao dentro de ax
Otras variaciones son posibles. Se puede sumar, restar, leer, escribir y combinar lgicamente
campos y registros. Recordar que en todos los casos, se tiene que proporcionar el nombre de la
estructura y la variable para que el ensamblador pueda generar la direccin correcta de los
campos.
inc
add
cmp
[AnioNuevo,anio]
[NuevoSiglo.anio],cx
[hoy.mes],8
db
10 DUP(?)
db
0,1,2,3,4,5,6,7,8,9
LXVIII
Lenguaje Ensamblador
.
Arreglos de otras estructuras tales como cadenas y variables STRUC toman ms tiempo. Por
ejemplo, supngase que se necesita un arreglo de 4 cadenas de 20 bytes. Dado que ste arreglo
es pequeo, se puede utilizar perfectamente cuatro variables separadamente:
unArreglo
db
db
db
db
20
20
20
20
DUP(?),0
DUP(?),0
DUP(?),0
DUP(?),0
;
;
;
;
unArreglo[0]
unArreglo[1]
unArreglo[2]
unArreglo[3]
Las cuatro variables son almacenadas consecutivamente en memoria, por lo tanto, las mismas
cadenas de 20 bytes (mas un byte para el terminador de la cadena), pueden ser accesadas como
variables individuales o como una estructura de cuatro cadenas. A menos que nos guste teclear
programas muy largos, esta forma de declarar arreglos puede ser inprctico para crear arreglos
largos. Considerar como crear espacio para un arreglo de 100 cadenas de 20 bytes. Utilizando
dos nuevas directivas LABEL y REPT, se puede escribir:
LABEL unArreglo
Byte
REPT 100
db
20 DUP(?),0
ENDM
La primer linea declara la etiqueta unArreglo de tipo Byte. Otros nombres que se pueden
utilizar aqu son Word, DWord, FWord, PWord, DataPtr, QWord, y TByte. O se puede utilizar un
nombre de estructura. La directiva LABEL informa al Turbo Assembler como direccionar el dato
que sigue - esto no reserva ningn espacio de memoria. En ste ejemplo, el dato que sigue son
cadenas, las cuales son siempre direccionadas como bytes. El comando REPT repite cualquier
sentencia del lenguaje ensamblador por un cierto nmero de veces, aqu 100. Todo entre REPT y
ENDM (Fin de Macro) es repetido como si se hubiese tecleado esta linea muchas veces.
Un truco til es cambiar la declaracin cada vez en la definicin. Por ejemplo, para crear un
arreglo de diez enteros y asignar los valores de 0 a 9 para cada posicin del arreglo, se puede
utilizar sta declaracin:
valor = 0
LABEL unArreglo
Word
REPT 10
dw valor
valor = valor + 1
ENDM
unArreglo
dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
0
1
2
3
4
5
6
7
8
9
LXIX
Lenguaje Ensamblador
.
el siguiente paso. Recordar que las expresiones tales como valor = valor + 1 son evaluadas en
tiempo de ensamble y que todas las acciones antes decritas toman lugar durante el ensamble no cuando el programa corre. El resultado es un arreglo de 10 palabras inicializada a valores
sucesivos. Ningn cdigo se genera con estos comandos.
LXX
Lenguaje Ensamblador
.
ax,[valorWord]
bl,[valorByte]
bh,[valorByte + 1]
El primer mov carga el valor completo de 16 bits, inicializando ax a 01234h. El segundo mov
almacena solamente los primeros 8 bits del mismo valor, inicializando bl a 034h. El tercer mov
carga los segundos 8 bits, inicializando bh a 012h. As, las dos ltimas instrucciones inicializan bx
al mismo valor que ax. (Recordar que las palabras son almacenadas con bytes en orden inversoel valor 01234h es almacenado en memoria como dos bytes 034h y 012h.
Utilizar LABEL para asignar etiquetas de diferentes tipos o variables siempre es mas til para
direccionar estructuras como colecciones de tipos de campos, pero tambin como cadenas de
palabras de 16 bits. Utilizando la estructura Fecha anteriormente descrita, se puede escribir:
LABEL Diames
unDia Fecha
word
<>
unDia es una variable estructurada de tipo fecha. La etiqueta Diames direcciona la misma
memoria pero considera el dato de tipo word. En el segmentode cdigo del programa, se pueden
referenciar al primero de dos campos en unDia normalmente como unDia.dia y unDia.mes. O,
dada la etiqueta adicional, se pueden cargar estos dos campos byte directamente en un registr
de 16 bits:
mov
mov
mov
ax,[Diames]
al,[unDia.dia]
ah,[unDia.mes]
El primer mov realiza la funcin identica a las utlimas dos intrucciones mov. Algunas veces, como
se muestra aqu, utilizar LABEL puede ayudar a ahorrar una o dos instrucciones y, si la instruccin
es repetida constantemente, esto mejorar el rendimiento del programa.
LXXI
Lenguaje Ensamblador
.
Indexando Arreglos.
Ahora que se sabe como declarar arreglos, el siguiente paso es investigar las formas de leer y
escribir valores en arreglos. Por ejemplo, como se hace referencia al elemento numero 5?. La
clave para contestar, est en que los ndices de un arreglo son simples direcciones- como
cualquier otra referencia a variables, por lo tanto, sin importar el tipo de dato almacenado en un
arreglo, el punto es indexar valores individuales reducindose esto a dos pasos:
-
Multiplicar el tamao de los elementos del arreglo por el ndice i del arreglo.
Sumar el resultado a la direccin base del arreglo.
Direcciones
Memoria baja
Indices
000D
10
[0]
000E
20
[1]
000F
30
[2]
0010
40
[3]
0011
50
[4]
0012
60
[5]
0013
70
[6]
0014
80
[7]
0015
90
[8]
0016
100
[9]
Por ejemplo, en un simple arreglo de bytes, si i es 0, entonces i x 2(0) mas la direccin del
arreglo localiza el primer valor en arreglo[0]. El segundo valor (arreglo[1]) es localizado en la
direccin base de arreglo mas 1, y as sucesivamente. Como se muestra en la figura, el punto es
convertir valores de ndices de arreglos a estas direcciones en memoria. El ndice 0 es
equivalente a la direccin, 00D - la misma que la direccin base del arreglo completo. El ndice 1
corresponde a la direccin 000E, el ndice 2, a 000F; hasta el ndice 9, el cual se localiza el valor
en el desplazamiento 0016. Los arreglos de bytes son los ms fciles de manipular. Para cargar
en al el elemento 64 de un arreglo de 100 bytes, se puede escribir:
DATASEG
unArreglo
db
100 DUP(0)
CODESEG
mov
al, [unArreglo + 63]
El colocar valores literales como el 63 en el ejemplo anterior no permite mucha flexibilidad. En la
mayora de las situaciones se utiliza un registro o una variable de memoria para almacenar el
indice del arreglo. Utilizando el modo de direccionamiento base, se puede almacenar el valor del
indice del arreglo en el registro bx. Por ejemplo, supongase que se tiene una variable llamada
indice y se requiere cargar el valor de unArreglo[indice] dentro de un registro:
DATASEG
indice
dw
?
unArreglo
db
100 DUP(0)
CODESEG
mov
bx, [indice]
mov
al, [unArreglo + bx]
LXXII
Lenguaje Ensamblador
.
Las dos declaraciones de datos reservan espacio para un indice de 16 bits y un arreglo sin
inicializar de 100 bytes. En el segmento de cdigo, el primer mov carga el valor actual de indice
dentro de bx. El segundo mov suma bx a la direccin base del arreglo, localizando el byte correcto
del arreglo dentro de al. Se pueden utilizar tambin los registros si y di para realizar lo mismo.
mov
mov
mov
mov
si,
al,
di,
al,
[indice]
[unArreglo + si]
[indice]
[unArreglo + di]
;
;
;
;
Las dos primeras lineas realizan lo mismo que las dos ltimas. Tcnicamente, este es el modo
de direccionamiento indexado no el modo de direccionamiento base, aunque como se puede
apreciar, no hay mucha diferencia practica entre los dos mtodos.
Elementos de arreglos multibyte
El direccionamiento de arreglos viene a ser mas complejo cuando los elementos de los arreglos
ocupan ms de 1 byte. Dada la naturaleza binaria de las computadoras, el calcular la direccin
de elementos de arreglos multibyte es mas simple cuando los tamaos de los elementos son
poderes de 2. En ste caso, se puede utilizar veloces instrucciones de corrimiento de bits para
realizar la multiplicacin inicial del indice por el tamao en bytes del elemento. Adicionando el
resultado de esta multiplicacin a la direccin base del arreglo localizando algn elemento, tal y
como lo demuestra el fragmento de cdigo a continuacin:
DATASEG
indice
dw
arreglo
dw
CODESEG
mov
bx,[indice]
shl
bx,1
mov
ax,[bx+arreglo]
1
100 DUP (?)
; Obtiene el valor del indice
; bx<- indice * tamanio_elemento(2)
; ax<- arreglo[indice]
En este ejemplo, el tamao del elemento es de 2 bytes; por lo tanto, la forma ms fcil ( y
rpida) de multiplicar el indice por 2 es realizar un corrimiento de bits del valor un bit a la
izquierda. Para localizar la direccin del quinto elemento de este arreglo, se debe multiplicar 4 x 2
y sumar el resultado a la direccin base del arreglo para obtener el valor final de desplazamiento.
Calcular la direccin indice cuando los tamaos de los elementos no son poderes de 2, requiere
de mayor esfuerzo para mantener el cdigo corriendo tan rpido como sea posible. Considere un
arreglo de elementos, cada uno ocupando 5 bytes. Para inicializar a bx a la direccin de
desplazamiento del elemento a cierto indice, requiere de varios pasos.
mov
mov
mul
mov
add
ax,[indice]
bx,5
bx
bx, ax
bx, OFFSET arreglo
LXXIII
Lenguaje Ensamblador
.
mov
mov
shl
shl
add
add
db ?
dw ?
Una directiva ENDS finaliza la unin. En ste ejemplo, unByte traslapa el primer byte de unWord,
Si esta fuera una estructura, entonces unByte y unWord podran ser almacenadas en localidades
consecutivas. Dada sta unin, unByte y unWord son almacenadas en la misma localidad de
memoria. Por lo tanto, al insertar un valor en unByte tambin cambia el LSB de unWord.
mov
[unByte], bh
Cuando se combinan con estructuras, las uniones dan poderosas formas de procesar variables.
Por ejemplo, el siguiente listado de cdigo:
STRUC
ENDS
DosBytes
ByteAlto
db
ByteBajo
db
DosBytes
UNION ByteWord
cByte
cWord
ENDS ByteWord
?
?
DosBytes <>
dw
1
La estructura DosBytes define dos campos byte, ByteAlto y ByteBajo. La union ByteWord
tambin define dos campos. Primero es cByte, de la estructura DosBytes previamente definida.
El segundo es cWord como una simple palabra de 16-bits. Variables de tipo ByteWord hacen fcil
de referir a localidades tanto como una palabra o dos valores bytes sin el peligro de olvidar que
LXXIV
Lenguaje Ensamblador
.
las palabras son almacenadas en bytes en orden inverso - un problema del mtodo LABEL. Para
usar la union anidada, primero se declara una variable, en ste caso asignando el valor 0FF00h.
dato
DATASEG
ByteWord
<,0FF00h>
Ahora se puede referir a dato como una estructura DosBytes o como una palabra de 16-bits. Un
corto ejemplo demuestra como cargar la misma localidad de memoria tanto en registros byte o
word. Dado que la estructura DosBytes est anidada dentro de la union, se requieren dos puntos
para "accesar" los campos byte. Note como los nombres de los campos reducen el peligro de
accidentalmente cargar el byte equivocado de una palabra en un registro de 8 bits.
mov
mov
mov
CODESEG
al,[dato.cByte.ByteBajo]
ah,[dato.cByte.ByteAlto]
ax,[dato.cWord]
Campos de Bits.
Muchas veces en la programacin en lenguaje ensamblador se necesita examinar y cambiar
uno o mas bits en un valor byte o word. Se pueden utilizar varias formas para completar la tarea
con instrucciones lgicas tales como or, and, y xor para inicializar o limpiar bits
individualmente sin afectar otros. Por ejemplo, para encender el bit nmero 2 en un registro byte,
se puede utilizar la instruccin:
or
al,00000100b
Cuando se hace esto, normalmente es ms til escribir el valor binario - solamente recordando
colocar la letra b al final del valor. La instruccin and puede enmascarar valores, inicializando uno
o mas bits a 0:
and
al, 11110000b
Aunque escribir valores en binario ayuda a clarificar exactamente cuales bits son afectados por
las instrucciones, se tienen que contar los bits y tomar algo de tiempo para visualizar el resultado
lgico.
En programas complejos, se muy fcil encender o apagar bits equivocados - un error muy difcil
de encontrar. Para realizar el procesamiento de bits de una forma mas fcil, Turbo Assembler
ofrece dos mecanismos - El registro RECORD y el enmascaramiento MASK.
Declarando Tipos RECORD
RECORD es una directiva que nos permite dar nombres de campos a bits dentro de bytes y
palabras. Simplemente especificando la longitud de cada campo - en otras palabras, el numero
de bits que ocupa el campo. Turbo Assembler calcula entonces la posicin del campo. Por
ejemplo, el siguiente registro RECORD define un byteconsigo como un valor de 8 bits con dos
campos:
RECORD ByteConSigno
signo:1, valor:7
Despus de la directiva RECORD, viene el nombre del registro, seguido por una serie de nombres
de campos. Cada campo termina con una coma y la longitud del campo en bits. El campo signo
en el ejemplo anterior es de 1 bit de longitud. El campo valor es de 7 bits de longitud.
Separando campos mltiples con comas. Si el total de numero de bits e menor o igual a 8, se
asume que el registro es de un byte; de otra forma, se asume que es de una palabra. No se
LXXV
Lenguaje Ensamblador
.
pueden construir registros mas grandes que una palabra, aunque se puedan crear estructuras de
mltiples campos. No es necesario especificar exactamente 8 o 16 bits.
Creando variables de tipo RECORD es similar a crear variables de estructuras o uniones.
v1
v2
v3
v4
v5
DATASEG
ByteConSigno
ByteConSigno
ByteConSigno
ByteConSigno
ByteConSigno
<>
<1>
<,5>
<1,127>
<3,300>
;
;
;
;
;
Valores
signo =
signo =
signo =
signo =
por default
1, valor = default
default, valor = 5
1, valor = 127
1, valor = 44
En la ltima linea se intenta insertar rangos de valores mayores a la capacidad que se puede
representar con la longitud de bits especificada para cada campo. Al realizar esto, lo que
realmente se inserta es el residuo de dividir el valor proporcionado entre 2 n, donde n es el
numero de bits de longitud del campo.
Utilizando Variables RECORD.
Despus de declarar un tipo RECORD, y unas cuantas variables de ste tipo, se pueden utilizar
varios mtodos para leer y escribir valores de campos de bits en esas variables. Para demostrar
como se hace esto, necesitamos primero un nuevo tipo RECORD.
RECORD
persona
RECORDS como este pueden empacar mucha informacin dentro de un espacio pequeo. En ste
ejemplo, solamente 16 bits son necesarios para almacenar 5 datos acerca de una persona. Con el
campo sexo igual a 0 para femenino y 1 para masculino, casado igual a 0 si es falso o 1 si es
cierto, hijos en un rango de 0 a 15, un bit reservado como xxx para un uso futuro, un campo
edad con un rango entre 0 y 127, y escuela desde 0 hasta 3, representando 4 niveles para la
escolaridad de una persona. Como con todos los valores de 16 bits, los dos bytes de 8-bits de
esta variable estn almacenados en orden inverso en memoria, con bits 0-7 en direcciones bajas
que 8 bits de 8-15.
El ensamblador convierte los nombres de campos de bits en un nmero de corrimiento de bits
de derecha a izquierda requeridos para mover el campo a la posicin extrema derecha en un byte
o palabra.
El valor es igual al bit posicin en el byte o palabra desde el bit menos significativo. En
referencia al registro persona, entonces, sexo = 15, casado = 14, hijos = 10, xxx = 9, edad = 2
y escuela = 0.
Se pueden utilizar estos nombres de campos como las constantes EQU. Almacenar un dato en
la posicin de un campo implica un procedimiento inverso, es decir, colocar el valor dentro de un
registro o localidad de memoria y aplicar un corrimiento de bits hacia la izquierda, el nmero de
posiciones necesarias para colocar el valor hasta su posicin especificada.
El utilizar nombres de campos en lugar de contar bits manualmente ahorra tiempo y ayuda a
prevenir errores. Por ejemplo, para incrementa el campo edad, se realiza el corrimiento de bits
requeridos hacia la extrema derecha en un registro palabra, incrementar el registro, y entonces
realizar un corrimiento hacia atrs a su posicin. Antes de hacer esto, obviamente, se deben
quitar los otros bits de la variable. Para ayudarnos con este paso, el ensamblador provee un
operador llamado MASK, el cual toma el nombre de un campo bit y genera una mascara and
apropiada con bits igual a 1 en todas las posiciones para este campo. Una buena forma de
organizar las mscaras es utilizar nombres similares a los campos asociados:
LXXVI
Lenguaje Ensamblador
.
maskSexo
maskCasado
maskHijos
maskEdad
maskEscuela
=
=
=
=
=
MASK
MASK
MASK
MASK
MASK
sexo
casado
hijos
edad
escuela
Cada nuevo identificador - por ejemplo, maskSexo y maskCasado - es asignada una mascara para
cada campo de bits. Los nombres realizan el propsito de hacer smbolos mas fciles de recordar,
sin importar el nombre que se utilice. No es necesario colocar la palabra mask como prefijo al
nombre del campo.
DATASEG
empleado
persona
<>
Para colocar un bit a 1, hay que utilizar la instruccin or combinando la mascara y el valor del
registro.
or
or
CODESEG
[empleado],maskSexo
[empleado],maskCasado
Para colocar los bits a 0, hay que utilizar el operador NOT junto con la mscara de bits para
cambiar el valor de todos los bits de la mscara. El ejemplo siguiente muestra el procedimiento:
and
mov
and
mov
ax, [empleado]
ax, maskHijos
cl, hijos
cl,cl
@@10
ax, cl
LXXVII
Lenguaje Ensamblador
.
@@10:
inc
ax
Realizar un corrimiento de bits hacia la derecha por la constante del nombre del campo
Aplicar un AND al registro con la mascara del campo
Aplicar un AND al valor original aplicando un NOT con la mscara del campo
Realizar un OR al regostro dentro del valor original
mov
shl
and
and
or
cl, hijos
ax, cl
ax, maskHijos
[empleado], NOT maskHijos
[empleado], ax
LXXVIII
Lenguaje Ensamblador
.
Entrada y Salida
Normalmente, la primera opcin es la mejor- otros mtodos de entrada estn disponibles para
pasar un Ctrl-C de regreso al programa tan solo como cualquier otra tecla presionada. Escribir un
manipulador de la interrupcin propio es probablemente un trabajo mas que innecesario. La
tercera opcin toma mas trabajo pero es mucho mas til, en algunos casos. Un manejador de
dispositivo es un programa en una forma altamente especializada que realiza una interface con
los dispositivos fsicamente tales como el teclado, impresoras y pantalla.
Hay que recordar siempre que tanto las funciones de entrada estandard y salida, 1 y 2 checan
si se presiona Ctrl-C. Cuando ocurre esto durante la llamada a la funcin de entrada 1 de DOS, el
programa nunca recibe el Ctrl-C. Cuando un Ctrl-C es detectado durante una llamada a la funcin
de salida 2 de DOS, el caracter en dl es pasado a la salida estandard antes que el chequeo de
Ctrl-C tome lugar.
Estos chequeos de caracteres especiales son llamados filtros por la manera en que estos evitan
el paso de ciertos caracteres presionados y caracteres de acciones especiales.
Entrada sin filtro
Cuando no se desea filtrar el Ctrl-C y otros cdigos de control, se puede usar una de dos
funciones:
-
La funcin 6 es incluida en DOS mas para acomodar programas convertidos desde el CP/M, los
cuales tienen una funcin similar para E/S directa a la consola. Dado que hay otros, y
LXXIX
Lenguaje Ensamblador
.
ah, 7
21h
Este mtodo no checa si se presiona Ctrl-C o Ctrl-Break y por lo tanto, previene de que los
usuarios terminen los programas prematuramente.
Para adicionar filtros a la entrada sin realizar un eco del caracter en el dispositivo de salida
estandard, se utiliza la funcin 8, la cual genera la interrupcin 23h para finalizar el programa.
Salida sin filtro
Como se explic anteriormente, se pueden escribir cadenas con el formato ASCII$ con la funcin
9 de DOS. Aparte de que el formato ASCII$ requiere extraamente de un signo de pesos como
terminador de la cadena, la funcin 9 detecta Ctrl-C y responde a otros cdigos de control. Si se
utilizan stas funciones para prevenir que usuarios interrumpan un programa, hay que llamar a la
funcin 44h "Controlador de Dispositivos" o IOCTL- disponible desde la versin 2. Esta funcin
permite reprogramar la salida del manejador del dispositivo para ignorar el Ctrl-C y el Ctrl-Break.
Primero, llamar a la funcin 44h con al igual a 0, leyendo los bits del dispositivo de control actual
desde el controlador de dispositivos:
mov ax, 4400h ; Funcin 44h, elemento 00:obtiene informacin del dispositivo
mov bx, 1
; Especifica una salida estandard
int 21h
; Llama a DOS. Retorna el dato en dx.
La configuracin en bits del controlador de dispositivos esta ahora en el registro dx. El bit 5 de
la configuracin del controlador de dispositivos informa si el manejador procesa todos los datos
(bit =1), o si filtra los caracteres Ctrl-C y Ctrl-Break (bit = 0). Encendiendo el bit 5 desactiva el
filtrado:
mov
xor
or
int
Esta tcnica deshabilita Ctrl-C, Ctrl-S, y Ctrl-P filtrando, no solamente al programa sino
tambin a cualquier otro programa incluyendo al mismo DOS que llama a las funciones 2 y 9 para
pasar datos al dispositivo de salida estandard. Despus de reprogramar el controlador de
dispositivos, no se podr presionar Ctrl-C para interrumpir el desplegado de un directorio largo
ejecutado por el comando DIR. Por lo tanto antes de que termine el programa, hay que colocar en
0 el bit 5 con las instrucciones mostradas anteriormente reemplazando or dl, 20h con and dl,
0DFh para restaurar el chequeo de Ctrl-C.
LXXX
Lenguaje Ensamblador
.
Esperando y Esperando
Un programa que lee una entrada va funciones 1, 7 y 8 de DOS, cae en un ciclo sin fin,
esperando por que se opriman teclas. Muchas veces, se querr que un programa responda a una
entrada de datos mientras realiza otra tarea si ninguna tecla se oprime. Por ejemplo, un
procesador de palabras puede realizar una operacin larga de bsqueda y reemplazo,
terminndola si se oprime la tecla ESC. O una simulacin puede actualizar la pantalla, tomando
varias acciones en tiempo real dependiendo de las teclas de comando que se opriman. Hay dos
formas de atacar este problema:
-
LXXXI
Lenguaje Ensamblador
.
LXXXII
Lenguaje Ensamblador
.
mm
aaa
00
00
00
00
00
00
00
00
01
01
01
01
01
01
01
01
10
10
10
10
10
10
10
10
11
11
11
11
11
11
11
11
000
001
010
011
100
101
110
111
000
001
010
011
100
101
110
111
000
001
010
011
100
101
110
111
000
001
010
011
100
101
110
111
Parte de desplazamiento
direccin
(BX)+(SI)
(BX)+(DI)
(BP)+(SI)
(BP)+(DI)
(SI)
(DI)
Direccin directa.
(BX)
(BX)+(SI)+nmero de 8 bits.
(BX)+(DI)+nmero de 8 bits.
(BP)+(SI)+nmero de 8 bits.
(BP)+(DI)+nmero de 8 bits.
(SI)+nmero de 8 bits.
(DI)+nmero de 8 bits.
(BP)+nmero de 8 bits.
(BX)+nmero de 8 bits.
(BX)+(SI)+nmero de 16 bits.
(BX)+(DI)+nmero de 16 bits.
(BP)+(SI)+nmero de 16 bits.
(BP)+(DI)+nmero de 16 bits.
(SI)+nmero de 16 bits.
(DI)+nmero de 16 bits.
(BP)+nmero de 16 bits.
(BX)+nmero de 16 bits.
registro AX (word) o AL (byte)
registro CX (word) o CL (byte)
registro DX (word) o DL (byte)
registro BX (word) o BL (byte)
registro SP (word) o AH (byte)
registro BP (word) o CH (byte)
registro SI (word) o DH (byte)
registro DI (word) o BH (byte)
de
la
LXXXIII
Lenguaje Ensamblador
.
para:
ADD AX,[SI]
00 000 011
00 000 100
Aqu tenemos que w=1, d=1(de memoria a registro), mm=00 (sin decalague), aaa=100 (modo
ndice, con el SI apuntado a los datos) y rrr=000 (registro AX para otro operando). Como no hay
decalague no hay bits adicionales.
Para optimizar ciertas combinaciones utilizadas con mucha frecuencia, especialmente aquellas
que utilizan los registros AX y Al.
La forma ms general tiene como fuente un dato inmediato y como destino un registro general
o una posicin de memoria. El primer byte es:
100000sw
Aqu, la s es un cdigo binario de 1 bit que indica el tamao del dato inmediato, y w es otro
cdigo binario de 1 bit que indica el tamao del dato destino. SI sw es 00, tanto el fuente como el
destino tienen 8 bits; si sw es 11, ambos datos son de 16 bits, y si sw es 01, indica que la fuente
es de 8 bits y s e debe ampliar a 16 bits.
El segundo byte es:
mm 000 aaa
Donde mm y aaa indican el modo de direccionamiento del punto de destino. El 000 que aparece
en el centro del byte no es una referencia a algn registro, sino que es parte del cdigo de
operacin, ayudando a especificar que se trata de una suma.
Dependiendo de mm y aaa, puede haber ms bits de decalague. Despus de la informacin
sobre el direccionamiento viene el dato inmediato. Si w=0 hay un byte de dato; si w=1 son dos
los bytes del dato.
El cdigo fuente en ensamblador del siguiente ejemplo es:
ADD AX,7
El registro AX es de 16 bits, por lo tanto w=1. El cdigo maquina ser:
0000010 1
00 000 111
00000000
LXXXIV
Lenguaje Ensamblador
.
PAQUETE DE RUTINAS
PARA ENTRADA/SALIDA
DE CADENAS
STRIO.ASM
LXXXV