Materia Global Lenguaje de Interdaz
-
Upload
zongolicaorizaba -
Category
Documents
-
view
67 -
download
1
description
Transcript of Materia Global Lenguaje de Interdaz
ANTOLOGÍA DE
LENGUAJES DE
INTERFAZ
Santiago Pavón Gutiérrez
Instituto tecnológico superior de Zongolica
SEMESTRE AGO 2014 – ENE 2015
PROPÓSITO DEL CURSO
La presente asignatura aporta al perfil del Ingeniero en Sistemas Computacionales
los conocimientos para el diseño e implementación de interfaces hombre-máquina
y máquina-máquina para la automatización de sistemas. El desarrollo,
implementación y administración de software de sistemas o de aplicación que
cumpla con los estándares de calidad con el fin de apoyar la productividad y
competitividad de las organizaciones. Para que desempeñe sus actividades
profesionales considerando los aspectos legales, éticos, sociales y de desarrollo
sustentable y a la vez le permita poseer las habilidades metodológicas de
investigación que fortalezcan el desarrollo cultural, científico y tecnológico en el
ámbito de sistemas computacionales y disciplinas afines.
Intensión didáctica
Se pretende dar un panorama general de lo que es el lenguaje ensamblador y
donde se puede utilizar. Dar a conocer las principales instrucciones y funciones
del lenguaje ensamblador, la forma de estructurar un programa, los parámetros
que se tienen que tomar en cuenta realizando ejemplos sencillos.
Se desarrollarán programas en lenguaje ensamblador que hagan uso de macros o
procedimientos, posteriormente, analizar el funcionamiento interno de los
programas desarrollados haciendo el uso del software que permita obtener datos
estadísticos sobre el funcionamiento de los mismos.
Logrando obtener los conocimientos necesarios para la programación de los
puertos de la computadora, así como, poder analizar la interfaz de video del buffer
en modo texto.
CONTENIDO
Lenguajes de Interfaz
Pagina Primera Parte
1 INTRODUCCION AL LENGUAJE ENSAMBLADOR 1.1 Importancia de la programación en lenguaje ensamblador………... 9 1.2 El procesador y sus registros internos. 1.3 La memoria principal (RAM). 1.4 El concepto de interrupciones. 1.5 Llamadas a servicios del sistema. 1.6 Modos de direccionamiento. 1.7 Proceso de ensamblado y ligado. 1.8 Desplegado de mensajes en el monitor.
Segunda Parte
2 PROGRAMACION BASICA 2.1 Ensamblador (y ligador) a utilizar. 2.2 Ciclos numéricos. 2.3 Captura básica de cadenas.
2.4 Comparación y prueba. 2.5 Saltos. 2.6 Ciclos condicionales. 2.7 Incremento y decremento. 2.8 Captura de cadenas con formato. 2.9 Instrucciones aritméticas. 2.10 Manipulación de la pila. 2.11 2.12
Obtención de cadena con representación decimal. Instrucciones lógicas.
2.13 Desplazamiento y rotación. 2.14 Obtención de una cadena con la representación hexadecimal. 2.15 Captura y almacenamiento de datos numéricos. 2.16 Operaciones básicas sobre archivos de disco.
Tercera Parte
3 Modularización 3.1 Procedimientos. 3.2 Macros.
Cuarta Parte 4 Programación de dispositivos
4.1 El buffer de video en modo texto. 4.2 Acceso a discos en lenguaje ensamblador. 4.3 Programación del puerto serial. 4.4 Programación del puerto paralelo. 4.5 Programación híbrida. 4.6 Programación de puerto usb.
RED CONCEPTUAL DEL CURSO
Programación Básica
Lenguajes de Interfaz
Modularización
Introducción al Lenguaje Ensamblador
Programación de dispositivos
OBJETIVOS DEL CURSO Al término del curso el participante:
1. Conocer cómo trabajan los microprocesadores con lenguaje ensamblador y
que aplicación pueden tener.
2. Utilizar las principales instrucciones del lenguaje ensamblador, para realizar
determinadas aplicaciones de interfaz.
3. Comprender la importancia de la utilidad de las macros y procedimientos
dentro del desarrollo de una aplicación de software.
4. Programar interfaces de software y hardware para la manipulación de
puertos y dispositivos de computadora.
UNIDAD 1
INTRODUCCIÓN A LOS LENGUAJES DE BAJO NIVEL
Un lenguaje de programación de características bajo nivel es aquel en el que sus
instrucciones ejercen un control directo sobre el hardware y están condicionados
por la estructura física de la computadora que lo soporta. El uso de la palabra bajo
en su denominación no implica que el lenguaje sea inferior a un lenguaje de alto
nivel, si no que se refiere a la reducida abstracción entre el lenguaje y el hardware.
Por ejemplo, se utiliza este tipo de lenguajes para programar tareas críticas de los
Sistemas Operativos, de aplicaciones en tiempo real o controladores de
dispositivos.
RED CONCEPTUAL DE LA UNIDAD
1.1 Importancia de la programación en
lenguaje ensamblador
Introducción al Lenguaje
Ensamblador
1.2 El procesador y sus registros internos
1.3 La memoria principal (RAM)
1.4 El concepto de interrupciones
1.5 Llamadas a servicios del sistema
1.6 Modos de direccionamiento
1.7 Proceso de ensamblado y ligado
1.8 Desplegado de mensajes en el monitor
Objetivo General de la Unidad:
Investigar la estructura y organización de un procesador.
Analizar los registros más importantes que contiene un CPU, así como las funciones de los mismos.
Descubrir modos de direccionamiento a memoria.
Estructurar un programa fuente y que esté despliegue mensajes en el monitor con instrucciones básicas en lenguaje ensamblador.
DESARROLLO DEL TEMA
1.1 Importancia de la programación en lenguaje ensamblador La importancia del lenguaje ensamblador radica principalmente 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 el 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. Permiten
adentrarnos al estudio del hardware de una PC. Este lenguaje proporciona las
herramientas para tomar control sobre todo lo que la computadora realiza
físicamente. Es importante como se puede ver, el Lenguaje Ensamblador es
directamente traducible al Lenguaje Máquina, y viceversa; simplemente, es una
abstracción que facilita su uso para los seres humanos.
Por otro lado, la computadora no entiende directamente al Lenguaje Ensamblador;
es necesario traducirle a Lenguaje Máquina. Pero, al ser tan directa la traducción,
pronto aparecieron los programas Ensambladores, que son traductores que
convierten el código fuente (en Lenguaje Ensamblador) a código objeto (es decir,
a Lenguaje Máquina). Surge como una necesidad de facilitar al programador la
tarea de trabajar con lenguaje máquina sin perder el control directo con el
hardware.
Ventajas:
Proporciona un control absoluto sobre la PC. Los programas en ensamblador son
rápidos y compactos.
• Velocidad.- Como trabaja directamente con el microprocesador al ejecutar
un programa, pues como este lenguaje es el más cercano a la máquina la
computadora lo procesa aún más rápido.
• Eficiencia de tamaño.- Un programa en ensamblador no ocupa mucho
espacio en memoria porque no tiene que cargar librerías y demás como son
los lenguajes de alto nivel.
• Flexibilidad.- Es flexible porque todo lo que puede hacerse con una
máquina, puede hacerse en el lenguaje ensamblador de esta máquina; los
lenguajes de alto nivel tienen en una u otra forma limitantes para explotar al
máximo los recursos dela máquina.
Desventajas:
• 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.
• 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.
• Peligro de afectar recursos inesperadamente.- Que todo error que
podamos cometer, o todo riesgo que podamos tener, podemos afectar los
recursos de la máquina, programar en este lenguaje lo más común que
pueda pasar es que la máquina se bloquee o se reinicie. 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.
• 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.
1.2 El procesador y sus registros internos
Todo procesador, grande o pequeño, desde el de una calculadora hasta el de una
súper computadora, ya sea de propósito general o específico, posee un lenguaje
único que es capaz de reconocer y ejecutar. Por razones que resultan obvias, este
lenguaje ha sido denominado Lenguaje de Máquina y más que ser propio de un
computador pertenece a su microprocesador.
El lenguaje de máquina está compuesto por una serie de instrucciones, que son
las únicas que pueden ser reconocidas y ejecutadas por el microprocesador. Este
lenguaje es un conjunto de números que representan las operaciones que realiza
el microprocesador a través de su circuitería interna. Estas instrucciones, por
decirlo así, están grabadas o "alambradas" en el hardware y no pueden ser
cambiadas.
El nivel más bajo al que podemos aspirar a llegar en el control de un
microprocesador es precisamente el del lenguaje de máquina.
Ahora bien, siendo el lenguaje de máquina un conjunto de números, ¿cómo es
capaz el microprocesador de saber cuándo un número representa una instrucción
y cuándo un dato? El secreto de esto reside en la dirección de inicio de un
programa y en el estado del microprocesador. La dirección de inicio nos indica en
qué localidad de memoria comienza un programa, y en consecuencia que datos
deberemos considerar como instrucciones. El estado del microprocesador nos
permite saber cuándo éste espera una instrucción y cuándo éste espera un dato.
• El cerebro del ordenador es el procesador. Su función es ejecutar los
programas almacenados en la memoria principal tomando las instrucciones,
examinándolas y ejecutándolas una tras otra. Para ello, el procesador
realiza todas las operaciones aritméticas, lógicas y de control que son
necesarias.
• Los registros del procesador se emplean para controlar instrucciones en
ejecución, manejar direccionamiento de memoria y proporcionar capacidad
aritmética.
Arquitectura:
• Unidad de control
• Unidad Aritmética lógica
• Registros Internos
• Buses internos
• Interrupciones
Esquema:
Secuencia de Acciones:
1. Se inicia en una posición de memoria definida.
2. Se lee el dato de esa posición y se manda al control.
3. La unidad de control decodifica la instrucción y la ejecuta en señales
adecuadas.
4. Se incrementa el contador del programa (registro que indica a que posición
se debe dirigir).
5. Se repite proceso desde el punto 2, hasta recibir una señal del exterior.
ALU: Circuito digital que realiza operaciones aritméticas y lógicas
Unidad de Control: Cerebro del microprocesador, genera señales de control
interno y externo.
Recibe códigos los cuales decodifica y ejecuta.
Los códigos pueden ser:
1. Operaciones aritmético lógicas
2. Cargar o leer datos
3. Saltos o interrupciones
Registros Internos:
Posiciones de memoria con utilidad general o especifica.
• Tipos:
– Registros de datos: operaciones aritméticas lógicas y manipulación
de datos
– Registros de Direcciones : para acceder a posiciones de memoria
• Contador de programa: leer o escribir datos de programa
• Puntero de pila: Recuperar y guardar datos de uso interno
• Índices: para acceder a posiciones de memoria en forma
relativa
– Registro de estado: para información especifica
• Los registros del procesador tienen como misión fundamental: almacenar
las posiciones de memoria que van a sufrir repetidas manipulaciones, ya
que los accesos a memoria son mucho más lentos que los accesos a los
registros.
• El 8086 dispone de 14 registros de 16 bits que se emplean para controlar la
ejecución de instrucciones, direccionar la memoria y proporcionar
capacidad aritmética y lógica. Cada registro puede almacenar datos o
direcciones de memoria. Los registros son direccionables por medio de un
nombre.
• Registros de propósito general o de datos, registros de segmento, registro
apuntador de instrucciones (IP), registros apuntadores (SP y BP), registros
índice (SI y DI) y registro de banderas, FLAGS o registro de estado (FL).
Registros de propósito general:
• Registro AX: Este registro es el acumulador principal, implicado en gran
parte de las operaciones de aritméticas y de E/S.
• Registro BX: Recibe el nombre de registro base ya que es el único registro
de propósito general que se usa como un índice en el direccionamiento
indexado. Se suele utilizar para cálculos aritméticos.
• Registro CX: El CX es conocido como registro contador ya que puede
contener un valor para controlar el número de veces que se repite una
cierta operación.
• Registro DX: Se conoce como registro de datos. Algunas operaciones de
E/S requieren su uso, y las operaciones de multiplicación y división con
cifras grandes suponen que el DX y el AX trabajando juntos.
Los registros de propósito general se pueden direccionar como una palabra o
como un byte. El byte de la izquierda es la parte Alta y el byte de la derecha es la
parte Baja.
Siguiendo esta nomenclatura, es posible referirse a cada uno de los dos bytes,
byte de orden alto o más significativo y byte de orden bajo o menos significativo,
de cada uno de estos registros. Por ejemplo: AH es el byte más significativo del
registro AX, mientras que AL es el byte menos significativo.
Un segmento es un área especial en un programa que inicia en un límite de un
párrafo, esto es, una localidad regularmente divisible entre 16 o 10 hex.
Un segmento en modo real puede ser de hasta 64k. Se puede tener cualquier
número de segmentos, para direccionar un segmento en particular basta cambiar
la dirección en el registro del segmento apropiado. Los tres principales segmentos
son: segmentos de código, de datos y de la pila.
Los registros de segmento son registros de 16 bits que constituyen la
implementación física de la arquitectura segmentada del 8086.
Registros de segmento
• Registro CS. Registro Segmento de Código. Establece el área de memoria
dónde está el programa durante su ejecución.
• Registro DS. Registro Segmento de Datos. Especifica la zona donde los
programas leen y escriben sus datos.
• Registro SS. Registro Segmento de Pila. Permite la colocación en memoria
de una pila, para almacenamiento temporal de direcciones y datos.
• Registro ES. Registro Segmento Extra. Se suele utilizar en algunas
operaciones con cadenas de caracteres para direccionar la memoria.
Registro Apuntador de Instrucciones (IP)
• Se trata de un registro de 16 bits que contiene el desplazamiento de la
dirección de la siguiente instrucción que se ejecutará. Está asociado con el
registro CS en el sentido de que IP indica el desplazamiento de la siguiente
instrucción a ejecutar dentro del segmento de código determinado por CS:
• Dirección del segmento de código en CS: 25A40H
• Desplazamiento dentro del segmento de código en IP:
25A40H + 0412H = 25E52H
• Dirección de la siguiente instrucción a ejecutar: 25E52H
Registros Apuntadores (SP y BP)
Los registros apuntadores están asociados al registro de segmento SS y permiten
acceder a los datos almacenados en la pila:
• Registro SP Proporciona un valor de desplazamiento que se refiere a la
palabra actual que está siendo procesada en la pila.
• Registro BP Facilita la referencia a los parámetros de las rutinas, los
cuales son datos y direcciones transmitidos vía la pila.
Registros Índice (SI y DI)
Los registros índices se utilizan fundamentalmente en operaciones con cadenas y
para direccionamiento indexado:
• Registro SI Registro índice fuente requerido en algunas operaciones con
cadenas de caracteres. Este registro está asociado con el registro DS.
• Registro DI Registro índice destino requerido también en determinadas
operaciones con cadenas de caracteres. Está asociado al registro DS o ES.
Registro de Banderas, FLAGS, o registro de estado (FL)
• Es un registro de 16 bits, pero sólo se utilizan nueve de ellos. Sirven para
indicar el estado actual de la máquina y el resultado del procesamiento. La
mayor parte de las instrucciones de comparación y aritméticas modifican
este registro. Algunas instrucciones pueden realizar pruebas sobre este
registro para determinar la acción siguiente.
• Los bits 0, 2, 4, 6, 7 y 11 son indicadores de condición que reflejan los
resultados de las operaciones del programa; los bits 8 al 10 son indicadores
de control que, modificados por el programador, sirven para controlar
ciertos modos de procesamiento, y el resto no se utilizan.
• OF. Bit de Overflow o desbordamiento. Indica desbordamiento de un bit de
orden alto (más a la izquierda), después de una operación aritmética.
• DF. Bit de Dirección. Designa la dirección, creciente (0) o decreciente (1),
en operaciones con cadenas de caracteres.
• IF. Bit de Interrupción. Indica que una interrupción externa, como la entrada
desde el teclado, sea procesada o ignorada.
• TF. Bit de Trap o Desvío. Procesa o ignora la interrupción interna de trace
(procesamiento paso a paso).
• SF. Bit de Signo. Indica el valor del bit más significativo del registro después
de una operación aritmética o de desplazamiento.
• ZF. Bit Cero. Se pone a 1 si una operación produce 0 como resultado.
• AF. Bit de Carry Auxiliar. Se pone a 1 si una operación aritmética produce
un acarreo del bit 3 al 4. Se usa para aritmética especializada (ajuste BCD).
• PF. Bit de Paridad. Se activa si el resultado de una operación tiene paridad
par.
• CF. Bit de Acarreo. Contiene el acarreo de una operación aritmética o de
desplazamiento de bits.
1.3 La memoria principal (RAM)
La memoria principal o primaria, "Memoria Central ", es aquella memoria de un
ordenador, la memoria es apta para 1200 gb, prácticamente la mejor, es un
dispositivo donde se almacenan temporalmente tanto los datos como los
programas que la CPU está procesando o va a procesar en un determinado
momento. Por su función, es una amiga inseparable del microprocesador, con el
cual se comunica a través de los buses de datos. Por ejemplo, cuando la CPU
tiene que ejecutar un programa, primero lo coloca en la memoria y después lo
empieza a ejecutar. lo mismo ocurre cuando necesita procesar una serie de datos;
antes de poder procesarlos los tiene que llevar a la memoria principal.
Esta clase de memoria es volátil, es decir que, cuando se corta la energía
eléctrica, se borra toda la información que estuviera almacenada en ella.
Por su función, la cantidad de memoria RAM de que disponga una computadora
es un factor muy importante; hay programas y juegos que requieren una gran
cantidad de memoria para poder usarlos. 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.
Tipos de memoria RAM
Existen y han existido muchos tipos de memorias RAM,
Para nombrar una memoria, hay que distinguir entre: soporte y características.
SIMMs y DIMMs
Se trata de la forma en que se juntan los chips de memoria, del tipo que sean,
para conectarse a la placa base del ordenador. Son unas plaquitas alargadas con
conectores en un extremo; al conjunto se le llama módulo.
El número de conectores depende del bus de datos del microprocesador, que más
que un autobús es la carretera por la que van los datos; el número de carriles de
dicha carretera representaría el número de bits de información que puede manejar
cada vez.
SIMMs: Single In-line Memory Module, con 30 ó 72 contactos. Los de 30 contactos
pueden manejar 8 bits cada vez, por lo que en un 386 ó 486, que tiene un bus de
datos de 32 bits, necesitamos usarlos de 4 en 4 módulos iguales. Miden unos 8,5
cm (30 c.) ó 10,5 cm (72 c.) y sus zócalos suelen ser de color blanco.
Los SIMMs de 72 contactos, más modernos, manejan 32 bits, por lo que se usan
de 1 en 1 en los 486; en los Pentium se haría de 2 en 2 módulos (iguales), porque
el bus de datos de los Pentium es el doble de grande (64 bits).
DIMMs: más alargados (unos 13 cm), con 168 contactos y en zócalos
generalmente negros; llevan dos muescas para facilitar su correcta colocación.
Pueden manejar 64 bits de una vez, por lo que pueden usarse de 1 en 1 en los
Pentium, K6 y superiores. Existen para voltaje estándar (5 voltios) o reducido (3.3
V).
Las SDRAM normales tienen 168 contactos, los primeros módulos se
comercializaban a 66MHz de velocidad, luego surgieron los de 100 y 133MHz, que
son prácticamente los únicos que se emplean en SDRAM, actualmente sólo se
encuentran fácilmente los SDRAM de 133MHz.
SDRAM: Sincronic-RAM. Funciona de manera sincronizada con la velocidad de la
placa (de 50 a 66 MHz), para lo que debe ser rapidísima, de unos 25 a 10 ns. Sólo
se presenta en forma de DIMMs de 168 contactos; es usada en los Pentium II de
menos de 350 MHz y en los Celeron.
1.4 El concepto de las interrupciones
Una interrupción es una instrucción que detiene la ejecución de un programa para
permitir el uso de la UCP a un proceso prioritario. Una vez concluido este último
proceso se devuelve el control a la aplicación anterior. Por ejemplo, cuando
estamos trabajando con un procesador de palabras y en ese momento llega un
aviso de uno de los puertos de comunicaciones, se detiene temporalmente la
aplicación que estábamos utilizando para permitir el uso del procesador al manejo
de la información que está legando en ese momento. Una vez terminada la
transferencia de información se reanudan las funciones normales del procesador
de palabras. Las interrupciones ocurren muy seguido, sencillamente la interrupción
que actualiza la hora del día ocurre aproximadamente 18 veces por segundo. Para
lograr administrar todas estas interrupciones, la computadora cuenta con un
espacio de memoria, llamado memoria baja, donde se almacenan las direcciones
de cierta localidad de memoria donde se encuentran un juego de instrucciones
que la UCP ejecutará para después regresar a la aplicación en proceso. La
sentencia para usar una interrupción en ensamblador es INT número. En el
programa anterior hicimos uso de la interrupción número 21h para llamar a DOS.
A continuación describiremos los 3 tipos de interrupciones:
INTERRUPCIONES INTERNAS DE HARDWARE:
Las interrupciones internas son generadas por ciertos eventos que surgen durante
la ejecución de un programa. Este tipo de interrupciones son manejadas en su
totalidad por el hardware y no es posible modificarlas. Un ejemplo claro de este
tipo de interrupciones es la que actualiza el contador del reloj interno de la
computadora, el hardware hace el llamado a esta interrupción varias veces
durante un segundo para mantener la hora actualizada. Aunque no podemos
manejar directamente esta interrupción (no podemos controlar por software las
actualizaciones del reloj), es posible utilizar sus efectos en la computadora para
nuestro beneficio, por ejemplo para crear un "reloj virtual" actualizado
continuamente gracias al contador del reloj interno. Únicamente debemos escribir
un programa que lea el valor actual del contador y lo traduzca a un formato
entendible para el usuario.
INTERRUPCIONES EXTERNAS DE HARDWARE:
Las interrupciones externas las generan los dispositivos periféricos, como pueden
ser: teclado, impresoras, tarjetas de comunicaciones, etc. También son generadas
por los coprocesadores. No es posible desactivar a las interrupciones externas.
Estas interrupciones no son enviadas directamente a la UCP, sino que se mandan
a un circuito integrado cuya función es exclusivamente manejar este tipo de
interrupciones. El circuito, llamado PIC 8259A, si es controlado por la UCP
utilizando para tal control una serie de vías de comunicación llamadas puertos.
INTERRUPCIONES DE SOFTWARE:
Las interrupciones de software pueden ser activadas directamente por el
ensamblador invocando al número de interrupción deseada con la instrucción INT.
El uso de las interrupciones nos ayuda en la creación de programas, utilizándolas
nuestros programas son más cortos, es más fácil entenderlos y usualmente tienen
un mejor desempeño debido en gran parte a su menor tamaño. Este tipo de
interrupciones podemos separarlas en dos categorías: las interrupciones del
sistema operativo DOS y las interrupciones del BIOS. La diferencia entre ambas
es que las interrupciones del sistema operativo son más fáciles de usar pero
también son más lentas ya que estas interrupciones hacen uso del BIOS para
lograr su cometido, en cambio las interrupciones del BIOS son mucho más rápidas
pero tienen la desventaja que, como son parte del hardware son muy específicas y
pueden variar dependiendo incluso de la marca del fabricante del circuito. La
elección del tipo de interrupción a utilizar dependerá únicamente de las
características que le quiera dar a su programa: velocidad (utilizando las del BIOS)
o portabilidad (utilizando las del DOS).
Interrupción 21H Propósito: Llamar a diversas funciones del DOS.
Sintaxis:
Int 21H
Nota: Cuando trabajamos en TASM es necesario especificar que el valor que
estamos utilizando es hexadecimal. Esta interrupción tiene varias funciones, para
acceder a cada una de ellas es necesario que el registro AH se encuentre el
número de función que se requiera al momento de llamar a la interrupción.
1.5 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.
.
1.6 Métodos de direccionamiento
Buses Internos: Caminos de comunicación que conectan dos o más dispositivos
para acceder a diferentes partes del circuito
1. Bus de dirección: para seleccionar posición de memoria para leer o escribir
datos
2. Bus de datos: transmitir datos
El microprocesador se divide por el número de bits que conforman el dato 4, 8,
16, 32, 46 bits
3. Bus de control: para sincronizar actividades y transacciones con los periféricos
del sistema.
Es la forma que tienen los Microprocesadores para indicar las diferentes fuentes
de datos, permitiendo una mayor flexibilidad al programador.
Cualquier instrucción posee 4 campos que indican a la unidad de control cual se la
operación, la ubicación del primer y segundo operador y el modo en que se deberá
buscar a 1 de los operandos.
El 8086 tiene 7 modos de direccionamiento conocidos como:
Direccionamiento inmediato: en este modo el operador se encuentra
directamente en la instrucción. Ejemplo: MOV AH, 234 o MOV DH, 0.
Modo registro: en este modo el operando se encuentra en un registro interno del
microprocesador. Ejemplo: MOV AH, AL.
Debe tenerse en cuenta que las operaciones entre registros se realizan con
registros de igual tamaño.
Modo directo: en este modo la ubicación del operando es una dirección de
memoria cuya posición se indica directamente en la instrucción. Ejemplo: MOV
AH, [102].
Modo indirecto: en este modo el operando se encuentra en una dirección de
memoria cuya posición está almacenada en un registro puntero (SI, SI, BX, BP)
identificada como Puntero índice (I) o Puntero base (B). Ejemplo MOV AH, [BX].
Modo indirecto con base: en este modo el operando se encuentra en una
posición de memoria cuya dirección es el contenido de un registro de base (BX,
BP) más un desplazamiento adicional de 8 o 126 bits. Ejemplo: MOV AH, [BX +
172].
Modo indirecto con índice: en este modo el operando se encuentra en una
posición de memoria cuya dirección es el contenido de un registro índice (SI, DI)
más un desplazamiento adicional de 8 a 16 bits. Ejemplo: MOV AH, [SI + 172].
Modo indirecto con base e índice: en este modo el operando se encuentra en
una posición de memoria cuata dirección es la contenida en un registro base (BX,
BP) más el contenido de un registro índice (SI, DI) más un desplazamiento de 8 a
16 bits. Ejemplo: MOV AH, [BP + SI + 18].
1.7 Proceso de ensamblado y ligado
Aun cuando el lenguaje ensamblador fue diseñado para hacer más fácil la
programación de bajo nivel, esta resulta todavía complicada y muy laboriosa. Por
tal motivo se desarrollaron los lenguajes de alto nivel, para facilitar la
programación de los computadores, minimizando la cantidad de instrucciones a
especificar. Sin embargo, esto no quiere decir que el microprocesador ejecute
dichos lenguajes. Cada una de las instrucciones de un lenguaje de alto nivel o de
un nivel intermedio, equivalen a varias de lenguaje máquina o lenguaje
ensamblador.
La traducción de las instrucciones de nivel superior a las de bajo nivel la realizan
determinados programas. Por una parte tenemos los intérpretes, como DBase,
BASIC, APL, y Lisp. En estos, cada vez que se encuentra una instrucción, se
llama una determinada rutina de lenguaje de máquina que se encarga de realizar
las operaciones asociadas, pero en ningún momento se genera un código objeto y
mucho menos un código ejecutable. Por otra parte, tenemos los compiladores,
como los desarrollados para Fortran, Clipper, COBOL, Pascal o C, que en vez de
llamar y ejecutar una rutina en lenguaje de máquina, éstos juntan esas rutinas
para formar el código objeto que, después de enlazar las rutinas de run-time y
llamadas a otros programas y servicios del sistema operativo, se transformará en
el programa ejecutable.
Finalmente, tenemos los ensambladores— como los descritos en este trabajo —
que son como una versión reducida y elemental de un compilador (pero que de
ninguna manera deben considerarse como tales), ya que lo único que tienen que
hacer es cambiar toda referencia simbólica por la dirección correspondiente,
calcular los saltos, resolver referencias y llamadas a otros programas, y realizar el
proceso de enlace. Los ensambladores son programas destinados a realizar el
ensamblado de un determinado código.
Para crear un programa ejecutable a partir de un código objeto se requiere que se
resuelvan las llamadas a otros programas y a los servicios del sistema operativo, y
agregar las rutinas o información de run-time para que el programa pueda ser
cargado a memoria y ejecutado. Este proceso es lo que se conoce como Link o
proceso de liga, y se realiza a través de un ligador o Linker que toma de entrada
el código objeto y produce de salida el código ejecutable.
Las rutinas de RUN-TIME son necesarias, puesto que el sistema operativo
requiere tener control sobre el programa en cualquier momento, además de que la
asignación de recursos y su acceso deben hacerse solamente a través del
sistema operativo. Para los computadores personales, esto no es tan complejo
como para otros computadores y sistemas operativos, pero es requerido.
Existen varios ensambladores disponibles para ambiente MS-DOS: el IBM Macro
Assembler, el Turbo Assembler de Borland, el Turbo Editassm de Speedware, por
citar algunos. Una breve descripción de cada uno se proporciona a continuación.
Macro Ensamblador IBM: Está integrado por un ensamblador y un
macroensamblador. En gran medida su funcionamiento y forma de invocarlo es
sumamente similar al de Microsoft. Su forma de uso consiste en generar un
archivo fuente en código ASCII, se procede a generar un programa objeto que es
ligado y se genera un programa .EXE. Opcionalmente puede recubrirse a la
utilería EXE2BIN de MS-DOS para transformarlo a .COM. Es capaz de generar un
listado con información del proceso de ensamble y referencias cruzadas.
Macro Ensamblador de Microsoft: Dependiendo de la versión, este ensamblador
es capaz de soportar el juego de instrucciones de distintos tipos de
microprocesadores Intel de la serie 80xx/80x86. En su versión 4.0 este soporta
desde el 8086 al 80286 y los coprocesadores 8087 y 80287. Requiere 128KB de
memoria y sistema operativo MS-DOS v2.0 o superior. Trabaja con un archivo de
código fuente creado a partir de un editor y grabado en formato ASCII. Este
archivo es usado para el proceso de ensamble y generación de código objeto.
Posteriormente, y con un ligador, es creado el código ejecutable en formato .EXE.
Turbo Editassm: Este es desarrollado por Speddware, Inc., y consiste de un
ambiente integrado que incluye un editor y utilerías para el proceso de ensamble y
depuración. Es capaz de realizar el ensamble línea a línea, conforme se
introducen los mnemónicos, y permite revisar listas de referencias cruzadas y
contenido de los registros. Este ensamblador trabaja con tablas en memoria, por lo
que la generación del código ejecutable no implica la invocación explícita del
ligador por parte del programador. Adicionalmente permite la generación de
listados de mensajes e información de cada etapa del proceso y la capacidad de
creación de archivos de código objeto.
Turbo Assembler (De Borland Intl): es muy superior al Turbo Editassm. Trabaja
de la misma forma, pero proporciona una interfaz mucho más fácil de usar y un
mayor conjunto de utilerías y servicios.
En lo que se refiere a las presentes notas, nos enfocaremos al Microsoft Macro
Assembler v4.0. Los programas ejemplo han sido desarrollados con éste y está
garantizado su funcionamiento. Estos mismos programas posiblemente funcionen
con otros ensambladores sin cambios o con cambios mínimos cuando utilizan
directivas o pseudoinstrucciones. Realmente la diferencia entre los ensambladores
radica en la forma de generar el código y en las directivas con que cuente, aunque
estas diferencias son mínimas. El código ensamblador no cambia puesto que los
microprocesadores con los que se va a trabajar son comunes. Así, todos los
programas que se creen con un ensamblador en particular podrán ser
ensamblados en otro, cambiando las pseudo-operaciones no reconocidas por el
equivalente indicado en el manual de referencia del paquete empleado.
1.8 Desplegado de mensajes en el monitor
Todos los gráficos y el texto que se muestran en el monitor se escriben en la RAM
de visualización de video, para después enviarlos 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.
Un monitor de pantalla de cristal líquido (LCD) digital directo recibe un flujo de bits
digitales directamente desde el controlador de video, y no requiere del barrido de
trama.
El uso de comentarios a lo largo de un programa puede mejorar su claridad, en
especial en lenguaje ensamblador, donde el propósito de un conjunto de
instrucciones con frecuencia no es claro. Un comentario empieza con punto y
coma (;) y, en donde quiera que lo codifique, el ensamblador supone que todos los
caracteres a la derecha de esa línea son comentarios. Un comentario puede
contener cualquier carácter imprimible, incluyendo el espacio en blanco.
Para poder desplegar mensajes en lenguaje ensamblador primero debemos
conocer la estructura del programa en ensamblador.
PALABRAS RESERVADAS
PAGE: designa el número máximo de líneas para listar en una página y el número
máximo de caracteres en una línea.
TITLE: para hacer que un título para un programa se imprima en la línea 2 de cada
página en el listado del programa
SEGMENT y ENDS
ASSUME
IDENTIFICADORES: es un nombre que se aplica a elementos en el programa.
OPERACIÓN
OPERANDO.
.
UNIDAD 2
PROGRAMACIÓN BASICA
Para comenzar con la programación en lenguaje ensamblador, es necesario
contar con un conjunto de herramientas de programación. Este conjunto de
herramientas consta de un editor de texto capaz de producir archivos en código
ASCII, un ensamblador y un enlazador.
RED CONCEPTUAL DE LA UNIDAD
2.1 Ensamblador (y ligador) a utilizar
Programación Básica
2.2 Ciclos numéricos
2.3 Captura básica de cadenas
2.4 Comparación y prueba
2.5 Saltos
2.6 Ciclos condicionales
2.7 Incremento y decremento
2.8 Captura de cadenas con formato
2.9 Instrucciones aritméticas
2.11 Obtención de cadena con representación
decimal
2.12 Instrucciones lógicas
2.13 Desplazamiento y rotación
2.14 Obtención de una cadena con la
representación hexadecimal
2.10 Manipulación de la pila
2.15 Captura y almacenamiento de datos
numéricos
2.16 Operaciones básicas sobre archivos de
disco
Objetivo General de la Unidad:
Realizar investigación y listar las principales instrucciones de programación en lenguaje ensamblador.
Desarrollar programas por medio de prácticas en lenguaje ensamblador, los
cuales ejemplifiquen las diferentes instrucciones y funciones básicas así como la forma de estructurarlas.
2.1 Ensamblador y ligador a utilizar Para crear un programa ejecutable a partir de un código objeto se requiere que se
resuelvan las llamadas a otros programas y a los servicios del sistema operativo, y
agregar las rutinas o información de run-time para que el programa pueda ser
cargado a memoria y ejecutado. Este proceso es lo que se conoce como Link o
proceso de liga, y se realiza a través de un ligador o Linker que toma de entrada
el código objeto y produce de salida el código ejecutable.
Las rutinas de RUN-TIME son necesarias, puesto que el sistema operativo
requiere tener control sobre el programa en cualquier momento, además de que la
asignación de recursos y su acceso deben hacerse solamente a través del
sistema operativo. Para los computadores personales, esto no es tan complejo
como para otros computadores y sistemas operativos, pero es requerido.
Existen varios ensambladores disponibles para ambiente MS-DOS: el IBM Macro
Assembler, el Turbo Assembler de Borland, el Turbo Editassm de Speedware, por
citar algunos. Una breve descripción de cada uno se proporciona a continuación.
Macro Ensamblador IBM: Está integrado por un ensamblador y un
macroensamblador. En gran medida su funcionamiento y forma de invocarlo es
sumamente similar al de Microsoft. Su forma de uso consiste en generar un
archivo fuente en código ASCII, se procede a generar un programa objeto que es
ligado y se genera un programa .EXE. Opcionalmente puede recubrirse a la
utilería EXE2BIN de MS-DOS para transformarlo a .COM. Es capaz de generar un
listado con información del proceso de ensamble y referencias cruzadas.
Macro Ensamblador de Microsoft: Dependiendo de la versión, este ensamblador
es capaz de soportar el juego de instrucciones de distintos tipos de
microprocesadores Intel de la serie 80xx/80x86. En su versión 4.0 este soporta
desde el 8086 al 80286 y los coprocesadores 8087 y 80287. Requiere 128KB de
memoria y sistema operativo MS-DOS v2.0 o superior. Trabaja con un archivo de
código fuente creado a partir de un editor y grabado en formato ASCII. Este
archivo es usado para el proceso de ensamble y generación de código objeto.
Posteriormente, y con un ligador, es creado el código ejecutable en formato .EXE.
Turbo Editassm: Este es desarrollado por Speddware, Inc., y consiste de un
ambiente integrado que incluye un editor y utilerías para el proceso de ensamble y
depuración. Es capaz de realizar el ensamble línea a línea, conforme se
introducen los mnemónicos, y permite revisar listas de referencias cruzadas y
contenido de los registros. Este ensamblador trabaja con tablas en memoria, por lo
que la generación del código ejecutable no implica la invocación explícita del
ligador por parte del programador. Adicionalmente permite la generación de
listados de mensajes e información de cada etapa del proceso y la capacidad de
creación de archivos de código objeto.
Turbo Assembler (De Borland Intl): es muy superior al Turbo Editassm. Trabaja
de la misma forma, pero proporciona una interfaz mucho más fácil de usar y un
mayor conjunto de utilerías y servicios.
En lo que se refiere a las presentes notas, nos enfocaremos al Microsoft Macro
Assembler v4.0. Los programas ejemplo han sido desarrollados con éste y está
garantizado su funcionamiento. Estos mismos programas posiblemente funcionen
con otros ensambladores sin cambios o con cambios mínimos cuando utilizan
directivas o pseudoinstrucciones. Realmente la diferencia entre los ensambladores
radica en la forma de generar el código y en las directivas con que cuente, aunque
estas diferencias son mínimas. El código ensamblador no cambia puesto que los
microprocesadores con los que se va a trabajar son comunes. Así, todos los
programas que se creen con un ensamblador en particular podrán ser
ensamblados en otro, cambiando las pseudo-operaciones no reconocidas por el
equivalente indicado en el manual de referencia del paquete empleado
Programa Descripción
MASM.EXE Microsoft Macro Assembler
SYMDEB.EXE Microsoft Symbolic Debuger Utility
LINK.EXE Microsoft 8086 object linker
MAPSYM.EXE Microsoft Symbol File Generator
CREF.EXE Microsoft Cross-Reference Utility
LIB.EXE Microsoft Library Manager
MAKE.EXE Microsoft Program Maintenance Utility
EXEPACK.EXE Microsoft EXE File Compression Utility
EXEMOD.EXE Microsoft EXE File Header Utility
COUNT.ASM Sample source file for SYMDEB session
README.DOC Updated information obtained after the manua was printed.
2.2 Ciclos Numéricos Comencemos por los sistemas de numeración que más utilizaremos al programar. El básico va a ser el sistema hexadecimal, aunque debemos de explicar antes el binario, el sistema de numeración que utiliza el ordenador. Los números que conocemos están escritos en base 10. Esto significa que tenemos, desde el 0 hasta el 9, diez símbolos para representar cada cifra. Es decir, cada cifra ir de 0 a 9, y al superar el valor "9", cambiar a 0 y sumar uno a su cifra de la izquierda: 9+1: 10.
El sistema binario utiliza tan sólo dos símbolos, el "0" y el "1". Imaginemos que tenemos el número binario "0". Al sumarle una unidad, este número binario cambiar a "1". Sin embargo, si volvemos a añadirle otra unidad, a este número en formato binario ser el "10" (aumenta la cifra a la izquierda, que era 0, y la anterior toma el valor mínimo).
Sumemos ahora otra unidad: el aspecto del número ser "11" (tres en decimal). Y podríamos seguir:
Binario : 0 ; 1 ; 10 ; 11 ; 100 ; 101 ; 110; 111 ; 1000 ; 1001 ; 1010,...
Decimal: 0 1 2 3 4 5 6 7 8 9 10
Esto nos permite establecer un sistema bastante sencillo de conversión del binario al decimal;
He aquí los valores siendo n el valor de la cifra:
Cifra menos significativa:
n*2^0 = 1 si n=1 o 0 si n=0
Segunda cifra:
n*2^1 = 2 si n=1 o 0 si n=0
Tercera cifra:
n*2^2 = 4 si n=1 o 0 si n=0
Cuarta cifra:
n*2^3 = 8 si n=1 o 0 si n=0
etc.,...
Y así continuaríamos, aumentando el número al que se eleva 2. Traduzcamos entonces el número binario '10110111'
2^7+ 0 +2^5+2^4+ 0 +2^2+2^1+2^0 = 128 + 0 + 32 + 16 + 4 + 2 + 1 = 183
1 0 1 1 0 1 1 1
De todos modos, esta transformación la he puesto simplemente para que se comprenda con más claridad cómo funcionan los números binarios. Es mucho más aconsejable el uso de una calculadora científica que permita realizar conversiones entre decimales, hexadecimales y binarios. Se hace su uso ya casi imprescindible al programar. La razón del uso de los números binarios es sencilla. Es lo que entiende el ordenador, ya que interpreta diferencias de voltaje como activado (1) o desactivado (0), aunque no detallaré esto. Cada byte de información está compuesto por ocho dígitos binarios, y a cada cifra se le llama bit. El número utilizado en el ejemplo, el 10110111, sería un byte, y cada una de sus ocho cifras,
un bit. Y a partir de ahora, cuando escriba un número binario, lo haré con la notación usual, con una "b" al final del número (ej: 10010101b)
La conversión a hexadecimal es muy utilizada en ensamblador, se trata de un sistema de numeración en base dieciséis. Por tanto, hay dieciséis símbolos para cada cifra, y en vez de inventarse para ello nuevos símbolos, se decidió adoptar las primeras letras del abecedario. Por lo tanto, tendremos ahora:
Hex Dec
1 --> 1
2 --> 2
3 --> 3
4 --> 4
5 --> 5
6 --> 6
7 --> 7
8 --> 8
9 --> 9
A --> 10
B --> 11
C --> 12
D --> 13
E --> 14
F --> 15
10 --> 16
11 --> 17
Etc,...
Como vemos, este sistema nos planteas bastantes problemas para la conversión, una calculadora científica será casi imprescindible para realizar esta operación.
Por que utilizar este sistema? Bien sencillo. Volvamos al byte, y traduzcamos su valor más alto, "11111111". Resulta ser 256. Ahora pasemos esta cifra al sistema hexadecimal, y nos resultará "FF". Obtenemos un número más comprensible que el binario (difícil de recordar), y ante todo mucho más compacto, en el que dos cifras nos representaran cada byte. Podremos además traducir fácilmente el binario a hexadecimal con esta tabla; cada cuatro cifras binarias pueden traducirse al hexadecimal:
Binario
Hexadecimal
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 A
1011 B
1100 C
1101 D
1110 E
1111 F
Por ejemplo, el número binario:
1111 0011 1010 1110
En hexadecimal sería:
1111 0011 1010 1110
F 3 A E
Para referirnos a un número hexadecimal sin especificarlo, usaremos la notación que se suele usar al programar, con un 0 al principio (necesario cuando hay letras) y una h al final, por ejemplo, el número anterior sería 0F3AEh
2.3 Captura básica de cadenas 2.4 Comparación y prueba
2.5 Saltos Los saltos incondicionales en un programa escrito en lenguaje ensamblador están
dados por la instrucción jmp, un salto es alterar el flujo de la ejecución de un
programa enviando el control a la dirección indicada.
2.6 Ciclos condicionales Un ciclo, conocido también como iteración, es la repetición de un proceso un cierto
número de veces hasta que alguna condición se cumpla. En estos ciclos se
utilizan los brincos "condicionales" basados en el estado de las banderas. Por
ejemplo la instrucción jnz que salta solamente si el resultado de una operación es
diferente de cero y la instrucción jz que salta si el resultado de la operación es
cero.
2.7 Incremento y decremento
2.8 Captura de cadenas con formato
Las instrucciones de manejo de cadenas difieren de las demás instrucciones del
8086 en que pueden accesar memoria e incrementar y decrementar un registro
apuntador en una sola instrucción.
Como su nombre implica, las instrucciones de cadena son particularmente útiles
en la manipulación de cadenas de caracteres. Son también adecuadas para el
manejo de arreglos, búfers de datos y todo tipo de cadenas de bytes y palabras.
Además, generan menos códigos y son más rápidas que las combinaciones
equivalentes de instrucciones normales del 8086, tal como LOOP, INC y MOV.
Las instrucciones de cadena pueden agruparse en los siguientes grupos
funcionales: instrucciones usadas para el movimiento de datos (LODS, STOS y
MOVS) e instrucciones de cadena para inspección y comparación de datos (SCAS
y CMPS).
2.9 Instrucciones aritméticas Las instrucciones de las operaciones lógicas son: AND, NOT, OR y XOR, éstas
trabajan sobre los bits de sus operandos. Para verificar el resultado de
operaciones recurrimos a la instrucción CMP. Las instrucciones utilizadas para las
operaciones algebraicas son: para sumar ADD, para restar SUB, para multiplicar
MUL y para dividir DIV.
Casi todas las instrucciones de comparación están basadas en la información
contenida en el registro de banderas. Normalmente las banderas de este registro
que pueden ser directamente manipuladas por el programador son la bandera de
dirección de datos DF, usada para definir las operaciones sobre cadenas. Otra
que también puede ser manipulada es la bandera IF por medio de las
instrucciones STI y CLI, para activar y desactivar respectivamente las
interrupciones.
A continuación explicaremos brevemente las instrucciones aritméticas y lógicas
por separado:
OPERACIONES ARITMÉTICAS:
Las operaciones en aritmética binaria a entera permiten a la CPU realizar cálculos
con números enteros positivos y negativos con una representación en
complemento a 2.
• NEG operando: cambia el signo del operando. Equivaldría al NOT del número y
le sumaría 1.
• ADD destino, fuente: destino = destino + fuente.
• ADC destino, fuente: destino = destino + fuente + carry (acarreo).
• SUB destino, fuente: destino = destino - fuente.
• SBB destino, fuente: destino = destino - (fuente + acarreo).
• MUL operando: multiplica sin considerar el signo. Multiplica el acumulador {AL}
o {AX}por el operando fuente. Si el operando fuente es de tipo byte, el resultado se
almacena en AX y si es de tipo palabra el resultado se almacena en AX la parte
inferior y en DX la palabra superior.
Si tipo fuente = byte:
AX = AL * fuente (multiplicación sin signo)
Si tipo fuente = palabra:
DX, AX = AX * fuente (multiplicación sin signo)
Si mitad superior (CF: acarreo) del resultado = 0
En CC CF = 1
• IMUL operando: multiplica considerando el signo.
• DIV operando: divide sin considerar el signo, un número contenido en el
acumulador entre el operando fuente. El cociente se almacena en el acumulador.
El resto se almacena en la extensión del acumulador. Si la extensión de AX será
DX (que ocurrirá cuando sea de tipo palabra), la operación y la extensión de AL
será AH.
IDIV operando: igual que el DIV pero considerando el signo.
• CBW: pasa de byte a palabra el contenido del acumulador.
• CWD: pasa de palabra a doble palabra el contenido del acumulador.
• INC destino: incrementa el destino.
• DEC destino: decrementa el destino.
2.10 Manipulación de la pila La pila conserva los datos de la BIOS cuando el ordenador está apagado. Dura
mucho (unos tres años de media), pero al final se agota. Para cambiarla, apunte
todos los datos de la BIOS, desconecte todo y sustitúyala por una igual, o bien por
un paquete externo de baterías que se conectan a un jumper (un microinterruptor)
de la placa base; ambas cosas las debería encontrar en tiendas de electrónica.
Después conecte todo, arranque el ordenador, entre en la BIOS y reintroduzca
todos los datos, ya que se habrán borrado. ¿Se imagina si no tuviera una copia
escrita qué aventura? A mí me pasó hace años, y no me quedó más remedio que
aprender sobre BIOS... bueno, no hay mal que por bien no venga.
2.11 Obtención de cadena con representación 2.12 Instrucciones lógicas
OPERACIONES LÓGICAS:
Hay cuatro operaciones básicas que se pueden realizar con un número binario, y coinciden con operaciones de la lógica matemática, con lo que cualquiera que la haya estudiado tendrá cierta ventaja para entenderla. Para explicarlas, llamar‚ al valor 0 resultado "falso", y al valor 1 "verdadero". Las operaciones son AND, OR, XOR y NOT
AND
Es un 'y' lógico. Se realiza entre dos cifras binarias confrontando cada cifra con su correspondiente, y el resultado será "1" si las dos son verdaderas (si las dos valen "1”), y "0" (falso) en el resto de los casos.
AND
1er. numero
2do. numero
Resultado
1 1 1
1 0 0
0 1 0
0 0 0
Vuelvo a la lógica para explicarlo más claramente: Imaginemos la frase: "El hombre es un mamífero y camina erguido". El hecho de que el hombre sea un mamífero es cierto (1), y el de que camine erguido, otro (1). Por lo tanto, al unirlos mediante una conjunción (‘y’ o ‘AND’), resulta que ya que se dan las dos, la oración es verdadera.
Pongamos un ejemplo más complejo, queremos realizar un AND lógico entre dos bytes:
11011000 AND 01101001
Observemos lo que sucede:
11011000 216 AND 01101001
En sistema decimal sería: AND 105 (aunque en sistema decimal 01001000 es mas lioso)
Cuando coinciden dos valores de "verdad", el resultado es "verdad", si uno es falso, el resultado es "falso" (no es verdad que "El hombre es un mamífero y
respira debajo del agua”), y si los dos son falsos, el resultado es falso (no es cierto que "El hombre es un ave y respira debajo del agua”)
OR
El "o" lógico. El resultado es "verdadero" cuando al menos uno de los factores es verdadero. O sea, es "1" cuando al menos uno de los dos factores es "1". Sería como la frase "Voy a buscar el peine o la caja de bombones", donde que uno sea cierto no significa que el otro no lo sea; es cierta la frase, es verdadera mientras uno de los términos sean verdaderos.
Operemos con los números "10100110" y "01101100":
10100110 OR 01101100 -------- 11101110
Como hemos visto, el valor 1 (verdadero) queda en las cifras de las que, confrontadas, al menos una es verdadera. Sólo resulta 0 (falso) si los dos números enfrentados son 0 (falsos).
XOR
"OR" exclusivo. Se trata de una orden parecida al OR, tan sólo que la verdad de una excluye la de la otra. El resultado, por tanto, es "1" (verdad) cuando uno y sólo uno de los dos números es verdadero (y el otro falso, claro). Sería como la oración "O vivo o estoy muerto", para que sea cierta se tiene que dar una de las dos, pero nunca las dos o ninguna.
10111001 XOR 01011101 -------- 11100100
La orden XOR va a ser bastante útil en encriptación, pero eso ya es otra historia,...
NOT
Esto se aplica sobre un sólo número, y en términos de lógica sería la negación de una oración, o sea, si el número al que se aplica es 1 el resultado es 0, y viceversa. En términos de lógica matemática aplicándolo a una oración, sería por
ejemplo, " No es verdad que tenga ganas de estudiar y de no beber ", negando las otras dos que en caso contrario serían verdad:
NOT 11100110 -------- 00011001
Se usan para realizar operaciones a nivel de bits.
• NOT operando: cambia los bits 1 por 0 y viceversa y devuelve el resultado en el
mismo operando.
AL = F2h AL 1111 0010
NOT AL; NOT AL 0000 1101 = Odh
• OR destino, fuente: operación o lógico inclusivo. El resultado se almacena en
destino.
AX = FEDCh= 1111 1110 1101 1100
BX = 1234 h = 0001 0010 0011 0100
OR AX, BX 1111 1110 1111 1100 = FEFC h
• AND destino, fuente: la operación Y lógica entre 2 operandos, el resultado se
deja en destino.
AX = FEDC h 1111 1110 1101 1100
BX = 1234 h 0001 0010 0011 0100
ADD AX, BX 0001 0010 0001 0100 = 1214 h
• XOR destino, fuente: la operación o lógico exclusiva; el resultado se deja en
destino.
AX = FEDC h 1111 1110 1101 1100
BX = 1234 h 0001 0010 0011 0100
XOR AX, BX 1110 1100 1110 1000 = ECE8 h
2.13 Desplazamiento y rotación 2.14 Obtención de una cadena con la representación hexadecimal
2.15 Captura y almacenamiento de datos numéricos 2.16 Operaciones básicas sobre archivos de disco
UNIDAD 3
MODULARIZACIÓN
Básicamente es crear varias rutinas (funciones o procedimientos) y así segmentar
el código y hacerlo más entendible para el programador ya sea para
actualizaciones o depuraciones.
Un módulo es un segmento, rutina, subrutina, sub algoritmo o procedimiento, que
puede definirse dentro de un algoritmo con el fin de ejecutar una tarea específica y
puede ser llamado o invocado desde el algoritmo principal cuando sea necesario
RED CONCEPTUAL DE LA UNIDAD
3.1 Procedimientos
Modularización
3.2 Macros
Objetivo General de la Unidad:
Realizar investigaciones sobre los conceptos macro y procedimiento, analizando sus semejanzas y diferencias.
Analizar el funcionamiento de un programa que no utiliza macros o
procedimientos en su funcionamiento, todo esto utilizando un software que permita obtener datos estadísticos del funcionamiento de los programas en depuración.
Desarrollar programas en un lenguaje de programación que haga uso de
macros o procedimientos, posteriormente analizar el funcionamiento interno de los programas desarrollados haciendo el uso del software que permita obtener datos estadísticos sobre el funcionamiento de los mismos.
3.1 Procedimientos Los procedimientos o rutinas, que son una serie de pasos que se usarán
repetidamente en el programa y en lugar de escribir todo el conjunto de pasos
únicamente se les llama por medio de la instrucción call.
Un procedimiento en ensamblador es aquel que inicie con la palabra Proc y
termine con la palabra ret.
Realmente lo que sucede con el uso de la instrucción call es que se guarda en la
pila el registro IP y se carga la dirección del procedimiento en el mismo registro,
conociendo que IP contiene la localización de la siguiente instrucción que
ejecutara la UCP, entonces podemos darnos cuenta que se desvía el flujo del
programa hacia la dirección especificada en este registro. Al momento en que se
llega a la palabra ret se saca de la pila el valor de IP con lo que se devuelve el
control al punto del programa donde se invocó al procedimiento.
Es posible llamar a un procedimiento que se encuentre ubicado en otro segmento,
para esto el contenido de CS (que nos indica que segmento se está utilizando) es
empujado también en la pila.
La manera más fácil de construir el programa en módulos, es dividirlo en dos o
más partes. Para esto, es necesario que datos, símbolos, y demás valores de un
módulo sean reconocidos por el otro u otros módulos. Para este tipo de
declaraciones globales existen dos directivas:
PUBLIC nombre,,, que hace la variable, etiqueta o símbolo absoluto disponible para todos los programas.
EXTRN nombre:tipo,,, que especifica una variable, etiqueta o símbolo externos identificados por nombre y tipo (que puede ser BYTE, WORD, DWORD, QWORD, TBYTE, NEAR, FAR, o ABS, éste último para números absolutos).
El siguiente ejemplo ilustra el uso de las directivas. El primer listado corresponde al módulo principal, mientras que el segundo al módulo que contiene una rutina. Ambos módulos son archivos que se editan por separado, se ensamblan por separado, pero se ligan juntos.
MODULO PRINCIPAL: MAIN.ASM
NAME main
PUBLIC exit
EXTRN print:near
stack SEGMENT word stack 'STACK'
DW 64 DUP(?)
stack ENDS
data SEGMENT word public 'DATA'
data ENDS
code SEGMENT byte public 'CODE'
ASSUME cs:code, ds:data
start:
mov ax,data ; carga localizacion del segmento
mov ds,ax ; en el registro DS
jmp print ; va a PRINT en el otro modulo
exit:
mov ah,4ch
int 21h
code ENDS
END start
SUBMODULO: TASK.ASM
NAME task
PUBLIC print
EXTRN exit:near
data SEGMENT word public 'DATA'
entrada DB "Entrando a un submodulo....",13,10,"$"
salida DB ".......saliendo del submodulo.",01,07,13,10,"$"
data ENDS
code SEGMENT byte public 'CODE'
ASSUME cs:code, ds:data
print:
mov ah,06h ; Funcion para borrar pantalla
mov al,0 ; todas las lineas
mov cx,0 ; de 0,0
mov dh,24d
mov dl,79d
mov bh,0 ; atributo en lineas vacias
int 10h ; Servicio de e/s video
mov dx, OFFSET entrada
mov ah,09h
int 21h
mov dx, OFFSET salida
int 21h
jmp exit ; Regresa al otro modulo
code ENDS
END
3.2 Macros
La declaración de macros se hace a través de las directivas MACRO y ENDM. Su sintaxis es:
nombre MACRO [parámetros,,,]
declaraciones
ENDM
Los parámetros son los valores que se substituirán en la macro cada vez que se haga referencia a ésta.
Para la definición de procedimientos se emplean las directivas PROC y ENDP. Su sintaxis es:
nombre PROC [distancia]
sentencias
nombre ENDP
La distancia, que puede ser NEAR (default) o FAR permiten indicar el tipo de acciones a realizar en brincos y llamados a subrutinas. nombre se puede usar como dirección en llamados o brincos.
UNIDAD 4
PROGRAMACIÓN DE DISPOSITIVOS
Los dispositivos externos como terminales, impresoras y manejadores de disco, se comunican con el microprocesador vía los puertos de E/S. Un byte de 8 bits o una palabra de 16 bits puede ser transferido a través de un puerto de E/S. Dentro del 8086, los datos deben ser enviados siempre (o recibidos) del registro acumulador, AX. En los casos en que se transfieren únicamente 8 bits, se usa la mitad baja del acumulador, AL. La dirección de E/S se especifica como el contenido del registro DX, o como un valor inmediato contenido en la instrucción. En el caso posterior, solamente los primeros 256 puertos de E/S (direcciones de E/S 00h a FFh) pueden ser accesadas. Se muestran a continuación ejemplos de uso de las instrucciones IN y OUT.
RED CONCEPTUAL DE LA UNIDAD
4.1 El buffer de video en modo texto
Programación de
Dispositivos
4.2 Acceso a discos en lenguaje ensamblador
4.3 Programación del puerto serial
4.4 Programación del puerto paralelo
4.5 Programación híbrida
4.6 Programación de puerto USB
Objetivo General de la Unidad:
Analizar el funcionamiento del buffer de video de una computadora, mediante la lectura en modo texto del mismo.
Desarrollar programas en lenguaje ensamblador para acceder a los
dispositivos de almacenamiento de la computadora.
Diseñar una interfaz de hardware utilizando algún tipo de integrado programable.
Diseñar una interfaz de software en algún lenguaje de programación para controlar la interfaz de hardware utilizando los puertos paralelos, seriales y USB de la computadora.
4.1 El buffer de video en modo texto Buffer:
Es la ubicación de la memoria de un dispositivo digital o una computadora que
está reservada para el almacenamiento temporal de información. Mientras los
datos están en el buffer, aguardan para ser procesados.
Un ejemplo de buffer tiene lugar cuando se intenta ejecutar aplicaciones de audio
video directamente desde Internet, sin descargarlas a la computadora. Está
práctica, conocida como streaming, requiere de la utilización de un buffer para
reducir el riesgo de que se corte la reproducción ante problemas en el ancho de
banda.
4.2 Acceso a discos en lenguaje ensamblador 4.3 Programación del puerto serial 4.4 Programación del puerto paralelo 4.5 Programación hibrida 4.6 Programación de puerto USB
BIBLIOGRAFIA
Abel, P. (1966). Lenguaje Ensamblador y Programación para PC IBM y compatibles. USA: Pearson. KIP R. Irvine, Lenguaje ensamblador para computadoras basadas en Intel, Pearson Prentice Hall, 5ª edición, 2008.
Luna, C. (2004). Lenguaje Ensamblador. Recuperado el 12 de Septiembre de 2014, de http://leng-ensam.wikispaces.com/file/view/Antologia+Lenguaje+Ensamblador.pdf Rincón, L. (2012). Conceptos Básicos sobre programación en ensamblador. Recuperado el 15 de Octubre de 2014, de http://dac.escet.urjc.es/docencia/ETC-ITIG_LADE/teoria-cuat1/tema9_conceptos_basicos_ensamblador.pdf