INTRODUCCIÓN A LENGUAJE ENSAMBLADOR
Lenguaje
Ensamblador
Es un tipo de
lenguaje de bajo nivel utilizado para escribir programas informáticos, y
constituye la representación más directa del código máquina específico para
cada arquitectura de microprocesador.
*Es un lenguaje de
programación de bajo nivel. Consiste en un conjunto de mnemónicos que
representan instrucciones básicas para los computadores, microprocesadores,
microcontroladores y otros circuitos integrados programables.
La traducción de
los nemónicos a código máquina entendible por el microcontrolador la lleva a
cabo un programa ensamblador.
El programa
escrito en lenguaje ensamblador se denomina código fuente (*.asm).
El programa
ensamblador proporciona a partir de este fichero el correspondiente código
máquina, que suele tener la extensión *.hex.
1.1 Importancia de la Programación en Lenguaje
Ensamblador
· Su importancia radica principalmente en
que se trabaja directamente con el microprocesador; por lo cual se debe de
conocer el funcionamiento interno de este.
· Tiene la ventaja de que en él se puede
realizar cualquier tipo de programas que en los lenguajes de alto nivel no lo
pueden realizar.
· Los programas en ensamblador ocupan
menos espacio en memoria.
Es importante
porque nos proporciona las herramientas para interactuar con el hardware.
Permite la
creación de programas muy rápidos y pequeños, y una optimización y un control
que no se consigue con lenguajes de medio y alto nivel.
Ventajas
1. Velocidad: Como trabaja directamente con
el microprocesador al ejecutar un programa, la computadora lo procesa más
rápido.
2. Eficiencia de tamaño: Un programa en
ensamblador no ocupa mucho espacio en memoria.
3. Flexibilidad: Es flexible porque todo lo
que puede hacerse con una máquina, puede hacerse en el lenguaje ensamblador de
esta máquina. Puede hacer tareas específicas que en un lenguaje de alto nivel
no se pueden llevar acabo porque tienen ciertas limitantes que no se lo permite.
Desventajas
1. Tiempo de programación: Como es un
lenguaje de bajo nivel requiere más instrucciones para realizar el mismo
proceso, en comparación con un lenguaje de alto nivel. Por otro lado, requiere
de más cuidado por parte del programador, pues es propenso a que los errores de
lógica se reflejen más fuertemente en la ejecución.
2. Programas fuente grandes: Por las mismas
razones que aumenta el tiempo, crecen los programas fuentes; simplemente
requerimos más instrucciones primitivas para describir procesos equivalentes.
Esto es una desventaja porque dificulta el mantenimiento de los programas, y
nuevamente reduce la productividad de los programadores.
3. Peligro de afectar recursos
inesperadamente: Con todo error que podamos cometer, o todo riesgo que podamos
tener, podemos afectar los recursos de la máquina.
Lo más común que
pueda pasar es que la máquina se bloquee o se reinicialice, porque con este
lenguaje es perfectamente posible (y sencillo) realizar secuencias de
instrucciones inválidas, que normalmente no aparecen al usar un lenguaje de
alto nivel.
4. Falta de portabilidad: Porque para cada
máquina existe un lenguaje ensamblador; por ello, evidentemente no es una
selección apropiada de lenguaje cuando deseamos codificar en una máquina y
luego llevar los programas a otros sistemas operativos o modelos de
computadoras.
El procesador y sus registros internos
Un registro es una
memoria de alta velocidad y poca capacidad, integrada en el microprocesador.
Permite guardar transitoriamente y acceder a valores muy usados, generalmente
en operaciones matemáticas.
Su función es la de almacenar datos, siendo la manera más rápida de hacerlo por el sistema. Los registros se miden en número de bits que almacenan. La CPU, en cambio, comparte un conjunto de localidades de almacenamiento temporal de datos de alta velocidad, denominada con el mismo nombre: registro.
Su función es la de almacenar datos, siendo la manera más rápida de hacerlo por el sistema. Los registros se miden en número de bits que almacenan. La CPU, en cambio, comparte un conjunto de localidades de almacenamiento temporal de datos de alta velocidad, denominada con el mismo nombre: registro.
Los registros se dividen en 6 categorías:
*Registros de segmento.
*Registros de propósito general.
*Registros de apuntadores.
*Registros de banderas.
*Registros de puntero de instrucción
*Registros de pila.
Algunos ejemplos básicos de registros son:
*Contador de programa (PC).
*Registro de direcciones de la memoria (MAR).
*Registro de datos (RD).
*Registro de instrucciones (IR).
*Palabra de estado de programa (PSW).
*Registros de segmento.
*Registros de propósito general.
*Registros de apuntadores.
*Registros de banderas.
*Registros de puntero de instrucción
*Registros de pila.
Algunos ejemplos básicos de registros son:
*Contador de programa (PC).
*Registro de direcciones de la memoria (MAR).
*Registro de datos (RD).
*Registro de instrucciones (IR).
*Palabra de estado de programa (PSW).
La memoria principal (RAM)
La
memoria principal o primaria, "Memoria Central ", es aquella memoria
de un ordenador, donde se almacenan temporalmente tanto los datos como los
programas que la CPU está procesando o va a procesar en un determinado
momento. Por ejemplo, cuando la CPU tiene que ejecutar un programa,
primero lo coloca en la memoria y después lo empieza a ejecutar.
Otros
andarán más rápido si el sistema cuenta con más memoria RAM. La memoria Caché:
dentro de la memoria RAM existe una clase de memoria denominada Memoria Caché
que tiene la característica de ser más rápida que las otras, permitiendo que el
intercambio de información entre el procesador y la memoria principal sea a
mayor velocidad.
Está
formada por bloques de circuitos integrados o chips capaces de almacenar,
retener o "memorizar" información digital, es decir, valores
binarios; a dichos bloques tiene acceso el microprocesador de la computadora.
La MP se comunica con el microprocesador de la CPU mediante el bus de
direcciones.
El
ancho de este bus determina la capacidad que posea el microprocesador para el
direccionamiento de direcciones en memoria. En algunas oportunidades suele
llamarse "memoria interna" a la MP, porque a diferencia de los
dispositivos de memoria secundaria, la MP no puede extraerse tan fácilmente por
usuarios no técnicos.
La
MP es el núcleo del sub-sistema de memoria de una computadora, y posee una
menor capacidad de almacenamiento que la memoria secundaria, pero una velocidad
millones de veces superior. Si tienes más memoria almacenas más datos.
Características
de la Memoria
Las
magnitudes importantes que caracterizan la Memoria Central o Principal son:
·
Capacidad o tamaño de esta. Es
decir, el número de miles de posiciones que contiene. Normalmente se expresan
en K.palabras, aunque en los ordenadores personales al ser las palabras de 8
bits se expresan en K-bytes. En la actualidad, el tamaño de la palabra es
múltiplo del byte, ya que de esta forma el acceso a la misma puede hacerse
desde uno al ancho máximo del bus de datos, ahorrando en muchos casos tiempo.
Así tendremos palabras de 8, 16, 32, 64 bits y capacidades de siempre medidas
en potencia de dos: 8, 16, 64, 128 K...etc(siendo 1K igual a 1025).
·
Tiempo de Acceso. Es
el tiempo que invierte el ordenador desde que se emite la orden de
lectura-escritura, hasta que finaliza la misma. Este tiempo es muy pequeño, y
de él depende la potencia del ordenado. Son típicos tiempos del orden de
microsegundos e incluso del orden de 2 a 10 nanosegundos.
·
El tamaño de la celda define
su anchura de palabra, y viene fijado por el ancho del registro de información
de memoria. Si la palabra interna es superior a la de la memoria, necesitara
hacer más de un acceso para conseguir toda la información.
Concepto de interrupciones
INTERRUPCIÓN
Una interrupción consiste en un mecanismo que provoca la alteración del
orden lógico de ejecución de instrucciones como respuesta a un evento externo,
generado por el hardware de entrada/salida en forma asincrónica al programa que
está siendo ejecutado.
Procesamiento de una interrupción
·
Terminar la ejecución de la instrucción máquina en
curso.
·
Salvar el estado del procesador (valores de
registros y flags) y el valor del contador de programa, IP, en la pila, de
manera que, en la CPU, al terminar el proceso de interrupción, pueda seguir
ejecutando el programa a partir de la última instrucción.
·
La CPU salta a la dirección donde está almacenada
la rutina de servicio de interrupción (Interrupt Service Routine, o abreviado
ISR) y ejecuta esa rutina que tiene como objetivo atender al dispositivo que
generó la interrupción.
·
Una vez que la rutina de la interrupción termina,
el procesador restaura el estado que había guardado en la pila en el paso 2 y
retorna al programa que se estaba usando anteriormente.
Tipos de interrupciones
1.
Interrupciones de hardware. Estas son
asíncronas a la ejecución del procesador, es decir, se pueden producir en
cualquier momento independientemente de lo que esté haciendo el CPU en ese
momento
2.
Excepciones. Son aquellas que se producen
de forma síncrona a la ejecución del procesador. Normalmente son causadas al
realizarse operaciones no permitidas tales como la división entre 0, el desbordamiento,
el acceso a una posición de memoria no permitida, etc.
3.
Interrupciones por software. Son
aquellas generadas por un programa en ejecución. Para generarlas, existen
distintas instrucciones en el código máquina que permiten al programador producir
una interrupción
Sistemas de prioridad
El sistema operativo necesita un mecanismo para priorizar las
interrupciones y tratar primero las más urgentes. Para ello, existen varias
alternativas:
·
Interrupciones simultáneas: No tienen
por qué ocurrir de manera simultánea, sino que se refiere a que en un momento
dado puede haber varias interrupciones activas.
·
Interrupciones anidadas: Mientras
se está procesando una determinada rutina de servicio de interrupción sucede
otra señal de interrupción.
·
Inhibición de interrupciones: Se deshabilitan
las demás interrupciones mientras se está tratando una.
Determinación de la fuente que genera la interrupción
Hay distintas formas de identificar la fuente de una determinada
interrupción.
·
Polling: el microprocesador comprueba de manera
sistemática todos los dispositivos de manera que «busca» cuál de ellos
fue el que solicitó la interrupción.
·
Interrupciones vectorizadas: Como
ventajas podemos destacar que suele ser rápido, pero implica un alto costo en el
hardware.
·
Hardware paralelo: se utiliza
un registro de interrupción cuyos bits se controlan de forma independiente por
las señales de petición de interrupción de cada periférico. Según la posición
de cada bit en el registro, se establece la prioridad.
LLAMADAS A SERVICIOS DEL SISTEMA
Una llamada al sistema es un método o función que puede invocar un
proceso para solicitar un cierto servicio al sistema operativo. Dado que el
acceso a ciertos recursos del sistema requiere la ejecución de código en modo
privilegiado, el sistema operativo ofrece un conjunto de métodos o funciones
que el programa puede emplear para acceder a dichos recursos. En otras
palabras, el sistema operativo actúa como intermediario, ofreciendo una
interfaz de programación (API) que el programa puede usar en cualquier momento
para solicitar recursos gestionados por el sistema operativo.
Algunos ejemplos de llamadas al sistema son las siguientes:
·
Time: que permite obtener la fecha y hora del sistema.
·
Write: que se emplea para escribir un dato en un cierto
dispositivo de salida, tales como una pantalla o un disco magnético.
·
Read: que es usada para leer de un dispositivo de
entrada, tales como un teclado o un disco magnético
·
Open: que es usada para obtener un descriptor de un
fichero del sistema, ese fichero suele pasarse a write.
MODOS
DE DIRECCIONAMIENTO
Los modos de direccionamiento son las diferentes maneras de especificar
un operando dentro de una instrucción en lenguaje ensamblador. Un modo de
direccionamiento especifica la forma de calcular la dirección de memoria
efectiva de un operando mediante el uso de la información contenida en
registros y/o constantes, contenida dentro de una instrucción de la máquina o
en otra parte.
Tipos de
direccionamiento
Registro:
Sirve para especificar operandos que están en registros.
Implícito:
En este modo de direccionamiento no es necesario poner ninguna dirección
de forma explícita, ya que en el propio código de operación se conoce la
dirección de el/los operandos/s al (a los) que se desea acceder o con el/los
que se quiere operar.
Inmediato:
En la instrucción está incluido directamente el operando.
En este modo el operando es especificado en la instrucción misma. En
otras palabras, una instrucción de modo inmediato tiene un campo de operando en
vez de un campo de dirección. El campo del operando contiene el operando actual
que se debe utilizar en conjunto con la operación especificada en la instrucción.
Las instrucciones de modo inmediato son útiles para inicializar los registros
en un valor constante.
Cuando el campo de dirección especifica un registro del procesador, la
instrucción se dice que está en el modo de registro. Su valor es fijo, por lo
que se suele utilizar en operaciones aritméticas o para definir constantes y
variables. Como ventaja, no se requiere acceso adicional a memoria para obtener
el dato, pero el tamaño del operando está limitado por el tamaño del campo de
direccionamiento.
Las desventajas principales son que el valor del dato es constante y el
rango de valores que se pueden representar está limitado por el tamaño de este
operando.
Indirecto:
El campo de operando contiene una dirección de memoria, en la que se encuentra
la dirección efectiva del operando.
Si hace referencia a un registro de la máquina, la dirección de memoria
(dirección efectiva) que contiene el dato estará en este registro y hablaremos
de direccionamiento indirecto a registro; si hace referencia a una posición de
memoria, la dirección de memoria (dirección efectiva) que contiene el dato
estará almacenada en esta posición de memoria y hablaremos de direccionamiento
indirecto a memoria.
La desventaja principal de este modo de direccionamiento es que necesita
un acceso más a memoria que el directo. Es decir, un acceso a memoria para el
direccionamiento indirecto a registro y dos accesos a memoria para el
direccionamiento indirecto a memoria; por este motivo este segundo modo de
direccionamiento no se implementa en la mayoría de las máquinas.
Proceso de ensamblado y ligado
EDICION
Los archivos fuente de código ensamblador deben
estar en formato ASCII standard. Para esto puede usarse cualquier editor que
permita crear archivos sin formato, e.g. Edlin, Edit, Write, El editor del
Turbo Pascal, Works, Word, WordStar, etcétera. Las declaraciones pueden ser
introducidas en mayúsculas y/o minúsculas. Una buena práctica de programación
es poner todas las palabras reservadas (directivas e instrucciones) en
mayúsculas y todo lo del usuario en minúsculas para fines de facilidad de
lectura del código. Las sentencias pueden comenzar en cualquier columna, no
pueden tener más de 128 caracteres, no se permiten líneas múltiples ni códigos
de control, y cada línea debe ser terminada con una combinación de line-feed y
carriage-return. Los comentarios se declaran con; y terminan al final de la
línea.
ENSAMBLADO
El ensamblado se lleva a cabo invocando al MASM.
Este puede ser invocado, usando una línea de comando, de la siguiente manera:
MASM archivo [,[objeto][,[listado][,[cross]]]]][opciones][;] Dónde:
Objeto. - Es el nombre para el archivo objeto.
Listado. - Nombre del archivo de listado de
ensamblado. cross. Es un archivo de referencias cruzadas. LINK De la misma
forma que el ensamblado, la fase de liga se lleva a cabo con el LINK. Este
puede ser invocado de la misma forma que el MASM. Los parámetros que este
requiere son: LINK objeto [,[ejecutable][,[mapa][,[librería]]]]][opciones][;]
dónde:
Objeto. - Es el nombre para el archivo .OBJ
Ejecutable. - Nombre del archivo .EXE
Mapa. - Nombre del archivo mapa
Librería. - Nombre del archivo biblioteca de
rutinas
EJECUCION
Para la ejecución del programa simplemente basta
teclear su nombre en el prompt de MS-DOS y teclear ENTER. Con esto el programa
será cargado en memoria y el sistema procederá a ejecutarlo. El proceso
completo para poder crear un programa ejecutable con el Microsoft Macro
Assembler se muestra abajo.
Características del Proceso de Ensamblado y ligado.
- El programa utiliza un editor de texto para
crear un archivo de texto ASCII, conocido como archivo de código fuente.
- El ensamblador lee el archivo de código fuete
y produce un archivo de código objeto, una traducción del programa a
lenguaje máquina. De manera opcional, produce un archivo de listado. Si
ocurre un error, el programador debe regresar al paso 1 y corregir el
programa.
- El enlazador lee el archivo de código objeto y
verifica si el programa contiene alguna llamada a los procedimientos en
una biblioteca de enlace. El enlazador copia cualquier procedimiento
requerido de la biblioteca de enlace, lo combina con el archivo de código
objeto y produce el archivo ejecutable. De manera opcional, el enlazador
puede producir un archivo de mapa.
- La herramienta cargadora (loader) del sistema
operativo lee el archivo ejecutable y lo carga en memoria, y bifurca la
CPU hacia la dirección inicial del programa, para que éste empiece a
ejecutarse.
Desplegado de mensajes en el monitor.
Para poder desplegar un mensaje en el monitor es necesario que el texto
a desplegar se escriba en la RAM de visualización de video, para después ser
enviado al monitor mediante el controlador de video. El controlador de video es
en sí un microprocesador de propósito especial, que libera a la CPU principal del
trabajo de controlar el hardware de video.
Para hacer esto se pueden utilizar varios de los servicios con los que
cuenta el lenguaje ensamblador, los cuales se describen con detalle en el
apéndice A.
Para detener la pantalla y permitir al usuario ver lo que se ha
desplegado en la misma se utiliza el servicio 00 de la interrupción 16h.
Ejemplo:
mov dx,65
-> Asignar el Valor 65 ASCII
al registro DX
mov ah,02h ->
Asignar el valor 02h al registro AH, que
corresponde al servicio de
impresión de un caracter.
int 21h
-> Llamada a la interrupción 21h, de
la que se ejecutará el servicio 02h.
Comentarios
Publicar un comentario