Guia 2 Sistemas
Guia 2 Sistemas
Guia 2 Sistemas
Guía de laboratorio # 2.
Instructores:
Br. Luis Gerardo Perez Herrera.
Introducción
Puesto que desea conocerse el lenguaje ensamblador del 8086 (modo real), es importante aclarar
lo siguiente:
¿Por qué molestarse en aprender lenguaje ensamblador, cuando ahora podemos crear rutinas en
otros lenguajes como C, Basic u otros, en los cuales la programación es mucho más fácil?
Existen muchas ventajas de aprender lenguaje ensamblador como:
Dicho de otra forma, alguien puede construir una rutina que controle hardware desde cualquier
plataforma de alto nivel (por ejemplo, un programa que controle el movimiento de un motor de
pasos) y dicho programa puede funcionar perfectamente haciendo interfaz desde una PC
cualquiera. Sin embargo, el problema se presenta cuando se requiere que la aplicación se construya
con un hardware mínimo, donde usar una computadora haría incurrir en un gasto excesivo e
innecesario. Generalmente se opta por utilizar un pequeño microprocesador o microcontrolador de
baja velocidad (por ejemplo un 80286 o inferior); en estos casos el programa de control suele
guardarse en memorias ROM ó EPROM cuya capacidad por unidad difícilmente supera los 64K de
memoria. Claramente se observa que el ahorro de memoria y de hardware es un factor
determinante, por lo que es en estos casos cuando el lenguaje ensamblador se vuelve la opción más
adecuada.
Además, los programadores de las librerías de lenguajes de alto nivel programan en ensamblador,
puesto que necesitan que éstas se ejecuten a gran velocidad.
Marco Teórico
La diferencia entre programar en un lenguaje ensamblador y uno de alto nivel es similar a la
diferencia entre un auto con palanca de cambios y uno de transmisión automática: Con la
transmisión automática se gana facilidad, pero se pierde control.
Lenguaje Ensamblador
En la mayoría de lenguajes ensambladores, los programadores escogen los nombres del operador,
dejándonos seleccionar muchos de los operadores que necesitamos. Por ejemplo. Si movemos un
valor de memoria que se ha declarado hacia un registro (MOV AX, VALOR), MOV y AX ya son parte
del lenguaje, pero nosotros declaramos VALOR con todos sus atributos. Probablemente la ventaja
más importante de la programación simbólica, en lugar de usar patrones en bits, es el control que
se obtiene sobre lo que se ha dado en llamar binding (atadura), es decir la asignación de valores
directamente reconocibles por la máquina a expresiones simbólicas que uno puede usar en el
programa fuente.
Otra ventaja de programar en el lenguaje simbólico en lugar de en bits es que los símbolos permiten
ver la generalidad del programa. Aunque ambos son lenguajes simbólicos, hay al menos 3 áreas en
las cuales el lenguaje ensamblador nos permite más control sobre la computadora que un lenguaje
compilador:
Programas ensambladores
Un programa ensamblador es aquel que permite escribir código en lenguaje ensamblador en lugar
de tener que usar largas cadenas de bits en lenguaje máquina. La mnemotecnia es el arte de mejorar
la eficiencia de la mente humana. El código de operación mnemónica es un código en el cual los
nombres de las operaciones son abreviados y expresados mnemónicamente para facilitar recordar
la operación que representan. El programa ensamblador clásico toma una rutina y la convierte a
una forma simbólica binaria para más tarde procesarla por medio de un enlazador (linker). Así, con
el MASM de Microsoft la conversión es hecha en dos pasos; o sea que el código fuente es examinado
dos veces.
La estrategia de dos pasos es muy simple: el primer paso, a través del código fuente, recoge todas
las definiciones de símbolos en una tabla de símbolos. El segundo paso convierte el programa en
una forma simbólica a código binario usando la tabla de símbolos del primer paso.
Los ensambladores permiten usar códigos mnemónicos y que nombres simbólicos sean asignados a
localidades de memoria, proporcionan facilidades para direccionar los cálculos en términos de tales
nombres simbólicos y normalmente permiten introducir constantes numéricas y de caracteres de
diversas formas.
Una instrucción típica consiste de un código de operación, una dirección y uno o más campos de
registros. La dirección podría referirse a un área de datos por ejemplo. Un programa ensamblador
procesa un conjunto fijo de códigos mnemónicos y un conjunto de símbolos definidos por el
programador. La dirección de tales símbolos podrían ser definidas explícitamente o implícitamente
atándolas como rótulos a instrucciones particulares o palabras de datos.
Las directivas del ensamblador tienen dos propósitos: uno de ellos es el de brindar información para
controlar el proceso de ensamble. Además proporcionan una forma de definir palabras de datos en
un programa.
En su forma más simple, una macroinstrucción (un macro) es una sola instrucción de computadora
que representa una secuencia dada de instrucciones Los macros son usados más usados a menudo
para representar secuencias relativamente cortas de instrucciones o secuencias que involucran un
número relativamente grande de inserción de argumentos. Casi siempre un conjunto de macros se
combina en una biblioteca de macros. Un ejemplo muy común de esto es una biblioteca de macros
para ayudar a comunicarse con el sistema operativo.
A medida que vamos creando programas más y más extensos y complejos nos damos cuenta que
un determinado patrón de instrucciones aparece en varios lugares dentro de un programa, solo con
pequeñas variaciones. Esto es particularmente el caso si hay una operación común que requiere
varias instrucciones para su ejecución. En este caso es conveniente el ser capaz de escribir una sola
llamada y que sea el sistema el que genere la secuencia de instrucciones. Hay algunas ventajas en
esto:
Para trabajar con macros, se necesita una pieza de software llamada macroprocesadores, el cual es
generalmente parte de un lenguaje ensamblador. El trabajo de un macroprocesador es sencillo: El
programador proporciona algunas definiciones de macros y que es lo que las va a reemplazar; y el
macroprocesador luego reemplaza cada aparición del macro con su correspondiente secuencia de
instrucciones definidas.
En el MASM de Microsoft, un nuevo macro puede ser creado (o definido) en cualquier punto de un
programa.
Dado que el macroprocesador, ya sea que esté o no incluido en el ensamblador, es puesto en un
modo especial de creación de macro cuando encuentra una definición de macro. La creación de uno
no genera ninguna instrucción en el programa. Sólo una llamada explícita a un macro genera
instrucciones.
Componentes de un macro
Un macro está pensado para limitar el área de interés para cualquier otra tarea y para minimizar el
impacto de cambios posteriores. Esto lo consigue aislado y formalizando los canales de
comunicación, o interfaces entre sí mismo y otras componentes del programa.
Todos los macros en el MASM poseen un nombre, un inicio, un cuerpo y un final. Normalmente
especifican una lista de uno o más parámetros auxiliares que pueden ser parámetros pasados al
macro. El nombre de un macro es un símbolo estándar de ensamblador. Puede incluir de 1 a 31
caracteres alfanuméricos, incluso los caracteres especiales ($ _ ? . @).
Los nombres auxiliares son una lista de parámetros, separados por comas, los cuales serán utilizados
dentro del macro. Los parámetros son variables temporales cuyos valores podrían cambiar con cada
nueva invocación del macro. Estos parámetros pueden ser numéricos o textos (incluyendo nombres
de registros), otros nombres de macros mnemónicos y etiquetas de programa. Las etiquetas se
refieren o corresponden a valores numéricos o posiciones de memoria.
Cuando se invoca un macro, este es expandido de manera que los parámetros referenciados en el
cuerpo se reemplazan por los valores que les hemos pasado. El final es un ENDM, lo cual señala al
macroensamblador que el código del macro ha terminado.
Tal como veremos a continuación la estructura de un macro tiene muchos puntos en común con la
estructura de un programa completo en lenguaje ensamblador.
Debe aclararse que aunque en este ejemplo se han utilizado letras mayúsculas para las instrucciones
y las directivas, esto es indiferente para el ensamblador. Podemos incluso mezclar mayúsculas y
minúscula. CSEB significa lo mismo que CseB para el programa ensamblador. Además la línea de
instrucción puede comenzar en cualquier columna y no es obligatorio utilizar un formato tabulado
para el programa fuente, aunque se recomienda por motivos de claridad y legibilidad de un
programa.
Aunque en un programa en ensamblador es posible trabajar con los cuatro segmentos (CS, SS, DS,
ES), solamente es obligatorio el uso de dos segmentos: el de código y el de pila (stack). Para definir
un segmento utilizamos la directiva SEGMENT, la cual tiene el siguiente formato:
El nombre del segmento puede ser único o puede ser el nombre de varios segmentos. Si esto último
es el caso (varios segmentos tienen asignado el mismo nombre), el MASM trata a los segmentos
como si, fueran piezas de un único segmento.
La combinación indica la manera en que los segmentos serán combinados o cargados cuando se
ejecute el enlazador (linker). Si no se señala ningún tipo de combinación, cada segmento recibe su
propio segmento físico cuando es cargado en memoria. La combinación puede ser cualquiera de las
siguientes: PUBLIC, COMMON, AT (dirección), STACK, MEMORY.
PUBLIC indica que todos los segmentos con el mismo nombre y con atributo PUBLIC serán
encadenados juntos.
MEMORY indica que todos los segmentos con este atributo se colocarán en direcciones de número
mayor que cualesquiera segmentos. Con AT (memoria), el segmento se coloca en el párrafo indicado
por memoria, que puede ser cualquier expresión sólida; sin embargo no puede contener una
referencia a algún símbolo definido posteriormente en el archivo fuente.
La `clase` se emplea para hacer referencia a una colección de segmentos, los segmentos con el
mismo nombre de clase se colocan en memoria secuencialmente, siguiendo el orden en que los
encontró el enlazador.
La directiva PAGE (Líneas, columnas) sirve para indicar al ensamblador como queremos que nos
genere el listado ensamblado (los valores por defecto son 66 filas y 80 columnas).
Las directivas TITLE y SUBTTL, sirven para colocar un título y un subtítulo a las páginas del listado
ensamblado.
La directiva .8086 le indica al ensamblador que solo debe aceptar instrucciones válidas para los
procesadores 8086/8088.
La directiva ORG inicializa el contador de localidad del MASM. Este contador de localidad es el que
sirve al MASM para llevar el control de la posición actual en el equipo fuente.
La directiva COMMENT sirve para escribir comentarios. El comentario es encerrado por un símbolo
delimitador ($,&, , etc.).
La directiva DB sirve para reservar un área de memoria o para inicializar un área de memoria de 8
bits; a directiva DW reserva un área de 16 bits y DD un área de 32 bits.
En la línea de nuestro programa ejemplo hemos inicializado una parte de la memoria colocando 64
veces la cadena (`stack`)
La última línea de nuestro programa contiene la directiva END. La cual le indica al ensamblador que
hemos llegado al final del programa fuente. Si después de END colocamos una etiqueta, estamos
indicándole al ensamblador el punto de entrada (dónde comenzar a ejecutar).
Una vez que hemos creado nuestro archivo fuente (el cual debe llevar la extensión .ASM) estamos
preparados para utilizar el MASM. Vamos a asumir que tanto el programa fuente como los
programas del MASM se encuentran en un mismo directorio. Esto lo haremos por motivos de
facilidad y claridad de la explicación. Sin embargo debemos tener en cuenta que esto NO es lo
recomendable si queremos dedicarnos seriamente a la creación de programas; ya que por lo general
el programa procesador de textos se encuentra en un subdirectorio propio, mientras que el MASM
y el linker se encuentran en otro u otros directorios. Esto no será un problema si manejamos
aceptablemente los comandos del DOS, ya que la manera de invocar al MASM es muy parecida a la
sintaxis del DOS.
En esta ocasión utilizaremos la manera más sencilla de ejecutar el ensamble de nuestro programa,
pero se debe tener en cuenta que existen otras formas de invocar al MASM y también existen
algunas opciones que podemos escoger al momento de realizar el ensamble.
Si los archivos de nuestro interés se encuentran en el directorio raíz del disco A; a partir del prompt
del DOS escribimos:
MASM
El ensamblador nos responde pidiéndonos el nombre del archivo fuente que queremos ensamblar
(asume que tiene extensión .ASM). Entonces escribimos ese nombre (para este ejemplo es el
archivo PRIMASM.ASM)
Primasm
A continuación nos pide que indiquemos cual es el nombre que le queremos dar al archivo objeto
que se va a generar. Aparecerá entre corchetes el nombre que le será asignado si nosotros no le
indicamos otro nombre. Si aceptamos ese nombre, únicamente presionamos la tecla ENTER().
De igual manera nos pide que le indiquemos el nombre que queremos poner al listado ensamblado
y al archivo con la referencia cruzada. A diferencia de lo que sucede con el archivo objeto; si solo
presionamos la tecla ENTER le estamos indicando que NO queremos que cree esos archivos.
Para nuestro ejemplo si queremos esos dos archivos, por lo tanto escribimos:
Primasm
Primasm
Para finalizar, el MASM nos indica si detectó algún error. En caso de que no nos diga explícitamente
cual es el error cometido, puede indicarnos el número de error.
Suponiendo que no se ha detectado ningún error, el siguiente paso es utilizar el programa LINK para
crear un programa ejecutable y relocalizable a partir del programa objeto creado por el MASM.
link
A continuación, se nos pide que indiquemos el archivo objeto que se desea enlazar. En este caso,
el archivo es PRIMASM.OBJ.
A continuación, se nos pide introducir el nombre del programa ejecutable que va a ser creado. Por
defecto se crea un archivo con el mismo nombre, pero extensión .EXE (PRIMASM.EXE para este
caso). Si este nombre le parece adecuado, solamente presione ENTER ( ).
Finalmente, se pide el nombre que desea ponerle al archivo que contenga el mapa de símbolos. Se
pide también el nombre de las bibliotecas que se desean enlazar con nuestro programa objeto. De
momento no se trabajará con estas últimas peticiones, así que presionaremos [ENTER] 2 veces
seguidas ( ).
Si el enlazador (linker no encuentra ningún error, se creará el programa ejecutable. Para correrlo,
solamente escribimos su nombre a partir de la línea de comandos del DOS como se muestra:
Primasm
Ya que el programa no posee ninguna instrucción que genere alguna salida visible o audible, no será
posible apreciar el correcto funcionamiento del programa. Además, al correr el programa, se
perderá el control sobre la computadora. Esto se debe a que los programas escritos para correr bajo
DOS deben cumplir con algunas formalidades que permitan su ejecución normal y luego, al finalizar,
debe devolver el control al sistema operativo; pero dado que la creación de programas ejecutables
bajo el DOS NO es uno de los objetivos de esta práctica, se dejará para un laboratorio posterior.
El objetivo de esta práctica es la creación del listado ensamblado, lo cual ya se hizo. En este listado
ensamblado aparece tanto el código fuente como la representación del código de máquina para
cada instrucción ensamblada además de los números de línea asociados con cada línea de listado
(estos números sirven como una referencia para conocer la localización de símbolos) y una columna
mostrando el desplazamiento en hexadecimal (partiendo de cero) de cada instrucción que aparece
en el listado.
Para ver todo lo anterior, podemos escribir TYPE primasm.lst , o bien podemos auxiliarnos
de un procesador de textos tal como el block de notas (NOTEPAD) o cualquier otro.
1. Escriba el programa del apéndice A en un procesador de texto y cree un archivo ASCII puro
con extensión .ASM
2. Ensamble el programa y genere el código objeto respectivo. Si encuentra errores, corríjalos
e intente ensamblar nuevamente hasta tener éxito.
3. Imprima el código objeto.
4. Utilice el programa LINK (el enlazador) para crear el programa ejecutable.
5. Córralo.
6. Repita todos los pasos anteriores para el programa del apéndice B.
Asignaciones
✓ Diseñar un programa en el cual se ingresen dos números de un byte cada uno, y que solicite
la operación matemática a realizar, la cual se seleccionara de acuerdo a la siguiente tabla:
Letra Operación
S Suma
R Resta
M Multiplicación
D División
Cualquier otra letra Operación no valida
Sin que haga diferencia entre mayúsculas y minúsculas, es decir si se ingresa “S” o “s” el
programa siempre realice la suma y así con las demás instrucciones.
✓ Diseñe un programa con dos tablas de 10x5, es decir, tablas de 10 posiciones de 5 bytes
cada una de nombres USERS y PASSWORD la primera posición de la tabla USERS debe
contener 5 caracteres (USER1) y la primera posición de la tabla PASSWORD contener 5
caracteres (PASS1). En principio el programa debe solicitar un usuario y contraseña (que
serán los guardados por defecto), de lograr esto correctamente debe mostrarse un menú
estilo tabla
Apéndice A
PAGE 50,132
TITLE PRIMASM Primer programa en ensamblador (PRIMASM.ASM)
SUBTTL Uso de directivas y estructuras de un programa.
.8086
COMMENT +
DESCRIPCION: Este módulo limpia el contenido
del registro AX, haciéndolo cero.
Después coloca en el registro AX
el número 18.
+
DB 64 DUP ('STACK')
ORG 0
CODIGO ENDP
STACK ENDS
; Segmento de código:
FINAL:
MOV AX,400H ; Define el tiempo del retardo
; junto con CX.
RETARDO: MOV CX,0A000H ; El retardo variará según la
; velocidad del CPU.
; Aproximadamente 5 seg. en una
; CPU Pentium ® 75 MHz.
RETARDAR: LOOP RETARDAR
INC CX
DEC AX
JNZ RETARDO
MOV DI,0
MOV AL,' '
MOV AH,07H
MOV CX,2000
REP STOSW
RET
INICIO ENDP
CODE ENDS
END INICIO