jueves, 28 de febrero de 2019

Desplegado de mensajes en el monitor

Para poder desplegar los mensajes en lenguaje ensamblador es preciso conocer primero la estructura del lenguaje ensamblador, la cual es:


◘ 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 en un programa se imprima en la línea 2 de cada página en el listado del programa.
  • SEGMENTS Y ENDS
  • ASSUME
◘ Identificadores: nombre que se le da a algunos elementos del programa.
◘ Operación.
◘ Operando.


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.

Proceso de ensamblado y ligado


Pasos para llevar a cabo el proceso:

1. El programa utiliza un editor de texto para crear un archivo de texto ASCII, conocido como archivo de código fuente.

2. El ensamblador lee el archivo de código fuente 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.

3. 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.

4. La herramienta cargador (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.

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.

Diferentes arquitecturas de computadores varían mucho en cuanto al número de modos de direccionamiento que ofrecen desde el hardware. Eliminar los modos de direccionamiento más complejos podría presentar una serie de beneficios, aunque podría requerir de instrucciones adicionales, e incluso de otro registro. Se ha comprobado que el diseño de CPUs segmentadas es mucho más fácil si los únicos modos de direccionamiento que proporcionan son simples.

La mayoría de las máquinas RISC disponen de apenas cinco modos de direccionamiento simple, mientras que otras máquinas CISC tales como el DEC VAX tienen más de una docena de modos de direccionamiento, algunos de ellos demasiado complejos. El mainframe IBM System/360 disponía únicamente de tres modos de direccionamiento; algunos más fueron añadidos posteriormente para el System/390.

Cuando existen solo unos cuantos modos, estos van codificados directamente dentro de la propia instrucción (Un ejemplo lo podemos encontrar en el IBM/390, y en la mayoría de los RISC). Sin embargo, cuando hay demasiados modos, a menudo suele reservarse un campo específico en la propia instrucción, para especificar dicho modo de direccionamiento. El DEC VAX permitía múltiples operandos en memoria en la mayoría de sus instrucciones, y reservaba los primeros bits de cada operando para indicar el modo de direccionamiento de ese operando en particular.

Tipos de direccionamiento

◘ 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 operando/s al (a los) que se desea acceder o con el/los que se quiere operar.
Supongamos una arquitectura de pila, las operaciones aritméticas no requieren direccionamiento explícito por lo que se ponen como: - add - sub ...Porque cuando se opera con dos datos en esta arquitectura se sabe que son los dos elementos del tope de la pila. Ejemplo de una pila

1 2 3 4 5 6 <- pila top() es 1 ntop() es 2
Donde top() representa el tope de la pila y ntop() el siguiente al tope de la pila y son estos argumentos con los que se opera al llamar a una orden en concreto.

◘ 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.


◘ Directo: El campo de operando en la instrucción contiene la dirección en memoria donde se encuentra el operando.
En este modo la dirección efectiva es igual a la parte de dirección de la instrucción. El operando reside en la memoria y su dirección es dada directamente por el campo de dirección de la instrucción. En una instrucción de tipo ramificación el campo de dirección especifica la dirección de la rama actual.

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


◘ Absoluto: El campo de operando contiene una dirección en memoria, en la que se encuentra la instrucción. Y no se cancela.

◘ De registro: Sirve para especificar operandos que están en registros. En este modo, los operandos están en registros que residen dentro de la CPU.




◘ Indirecto mediante registros:El campo de operando de la instrucción contiene un identificador de registro en el que se encuentra la dirección efectiva del operando.

En este modo el campo de la dirección de la instrucción da la dirección en donde la dirección efectiva se almacena en la memoria. El control localiza la instrucción de la memoria y utiliza su parte de dirección para acceder a la memoria de nuevo para leer una dirección efectiva. Unos pocos modos de direccionamiento requieren que el campo de dirección de la instrucción sea sumado al control de un registro especificado en el procesador. La dirección efectiva en este modo se obtiene del siguiente cálculo:

         Dir. efectiva = Dir. de la parte de la instrucción + Contenido del registro del procesador.
◘ De desplazamiento:Combina el modo directo e indirecto mediante registros.
◘ De pila:Se utiliza cuando el operando está en memoria y en la cabecera de la pila.
Este direccionamiento se basa en las estructuras denominadas Pila (tipo LIFO), las cuales están marcados por el fondo de la pila y el puntero de pila (*SP). El puntero de pila apunta a la última posición ocupada. Así, como puntero de direccionamiento usaremos el SP.
El desplazamiento más el valor del SP nos dará la dirección del objeto al que queramos hacer referencia. En ocasiones, si no existe C. de desplazamiento solo se trabajara con la cima de la pila. Como es un modo de direccionamiento implícito, solo se utiliza en instrucciones determinadas, las más habituales de las cuales son PUSH (poner un elemento en la pila) y POP (sacar un elemento de la pila).
Este tipo de direccionamiento nos aporta flexibilidad pero por el contrario, es mucho más complejo que otros tipos estudiados más arriba.

◘ Relativo a un registro base:Consiste, al igual que el indirecto a través de registro, en calcular la dirección efectiva (EA, effective address) como la suma del contenido del registro base y un cierto desplazamiento (offset) que siempre será positivo. Esta técnica permite códigos reentrantes y acceder de forma fácil y rápida a posiciones cercanas de memoria.

Este modo de direccionamiento es muy usado por los ensambladores cuando se llaman a las funciones (para acceder a los parámetros almacenados en la pila).

◘ Relativo a un registro índice:
Es similar al direccionamiento relativo a un registro base, excepto que es el contenido del registro índice el que indica el desplazamiento que se produce a partir de una dirección de memoria que se pasa también como argumento a la orden que utiliza este modo de direccionamiento. Aunque en esencia son dos modos equivalentes. La EA se calcula como la suma del contenido del registro índice y una dirección de memoria.
◘ Indexado respecto a una base:Se trata de una combinación de los dos anteriores y consiste en calcular la dirección efectiva como:
  • Relativo al contador de programa:Consiste en dirección una posición de memoria usando como registro base al contador de programa (PC), el funcionamiento es análogo al direccionamiento respecto a registro base con la salvedad de que, en este caso, el offset puede ser también negativo.
  • Indexado con autoincremento/autodecremento:Es un modo de direccionamiento análogo al indexado, explicado anteriormente.
La única diferencia es que permite un incremento o decremento de la dirección final o el registro índice según los siguientes casos:
  • Indexado con autopreincremento:Incrementa el registro índice primero (se incrementa un valor, según el tamaño del objeto direccionado) y luego calcula la EA al igual que el direccionamiento indexado.
  • Indexado con autoposincremento: Calcula la dirección efectiva y después incrementa esta.
  • Indexado con autopredecremento: Decrementa el registro índice y después calcula la dirección efectiva.
  • Indexado con autoposdecremento: Calcula la dirección efectiva y después decrementa esta.

◘ Instrucción de salto con direccionamiento absoluto: Consiste en cargar en el PC el valor que se especifica, por ¿ejemplo: jmp 0xAB ----> Carga 0xAB en PC.
◘ Instrucción de salto con direccionamiento relativo:Es parecida a la especificada anteriormente la diferencia es que el salto es relativo al PC
Ejemplo:supongamos que PC vale = 0x0A, si nosotros interpretamos la instrucción jr +03, saltaremos tres posiciones posteriores a PC (también podría ser -03 y serían posiciones anteriores). Pero, ¡cuidado! si esa instrucción estaba en la posición 0x0A la dirección de PC a incrementar será la inmediatamente posterior (ya que PC se incrementa automáticamente después de leer la instrucción), por lo que quedaría:
       PC = 0x0B ---> nuevo PC = 0x0B+0x03 = 0x0E, con lo que el PC quedaría como 0x0E.
◘ Direccionamiento paginado: En el paginado la memoria se encuentra actualmente dividida en páginas (bloques de igual longitud). Para obtener las direcciones se necesita:

  • Indicador de página (IP):en un registro específico o de propósito general de la máquina.
  • Dirección de la palabra (DP):
    en el campo CD de la instrucción.


    Así, concatenando ambas partes se obtiene la dirección completa.


El problema viene cuando queremos referenciar un dato al que no podemos acceder de forma relativa (p.e. porque los registros base no puedan alcanzar dicha posición aun con el direccionamiento absoluto. Sin embargo, sólo una pequeña parte de la memoria se puede acceder (64 kilobytes, si el desplazamiento es de 16 bits).
El desplazamiento de 16 bits puede parecer muy pequeño en relación con el tamaño de la memoria de los equipos actuales (esta es la razón por la 80386 se expandió a 32 bits). Podría ser peor ya que: los sevidores IBM System/360 sólo tienen un signo de 12 bits de desplazamiento. Sin embargo, el principio de localización se aplica en un corto espacio de tiempo, la mayoría de los elementos de datos que un programa quiere acceder están bastante cerca uno del otro.
Este modo de direccionamiento está estrechamente relacionado con el modo de direccionamiento absoluto.

Ejemplo 1: Dentro de una subrutina, un programador estará principalmente interesados en los parámetros y las variables en los atributos del objeto actual.

Llamadas al servicio 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 requieren 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.
En los sistemas operativos bajo norma POSIX o similares, algunas llamadas al sistema muy usadas son: open, Read (system call), write, close, wait, exec, fork, exit y kill. Los sistemas operativos actuales tienen cientos de llamadas, por ejemplo, Linux 2.x y FreeBSD tienen más de 300.

Las llamadas al sistema comúnmente usan una instrucción especial de la CPU que causa que el procesador transfiera el control a un código privilegiado (generalmente es el núcleo), previamente especificado. Esto permite al código privilegiado especificar donde va a ser conectado, así como el estado del procesador.

Cuando una llamada al sistema es invocada, la ejecución del programa que invoca es interrumpida y sus datos son guardados, normalmente en su PCB (Bloque de Control de Proceso del inglés: Process Control Block), para poder continuar ejecutándose luego. El procesador entonces comienza a ejecutar las instrucciones de código de bajo nivel de privilegio, para realizar la tarea requerida. Cuando esta finaliza, se retorna al proceso original, y continúa su ejecución. El retorno al proceso demandante no obligatoriamente es inmediato, depende del tiempo de ejecución de la llamada al sistema y del algoritmo de planificación de CPU.

Generalmente, los sistemas operativos proveen bibliotecas que relacionan los programas de usuario y el resto del sistema operativo, usualmente una biblioteca C como glibc o el runtime de Microsoft C. Esta biblioteca maneja los detalles de bajo nivel para transferir información al kernel y conmutar a modo supervisor, así como cualquier procesamiento de datos o tareas que deba ser realizada en modo supervisor. Idealmente, esto reduce la dependencia entre el sistema operativo y la aplicación, e incrementa su portabilidad.

La implementación de las llamadas al sistema requiere un control de transferencia que involucra características específicas de la arquitectura del procesador. Una forma típica de implementar es usar una interrupción por software. Linux usa esta implementación en la arquitectura x86. 

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
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
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.
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 pueden 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.

Memoria principal



La memoria principal en una computadora se denomina memoria de acceso aleatorio. También es conocida como RAM. Esta es la parte de la computadora que almacena software del sistema operativo, aplicaciones de software y otra información para la unidad de procesamiento central (CPU) y así tener acceso rápido y directo cuando sea necesario para realizar las tareas. Se llama "acceso aleatorio" porque la CPU puede acceder directamente a una sección de la memoria principal, y no debe emprender el proceso en un orden secuencial.

La RAM es uno de los tipos más rápidas de memoria, y tiene la capacidad de permitir que los datos sean leídos y escritos. Cuando la computadora está apagada, todo el contenido almacenado en RAM se purga. La memoria principal está disponible en dos tipos: la memoria dinámica de acceso aleatorio (DRAM) y la memoria estática de acceso aleatorio (SRAM).

La RAM tiene dos modos de operación posibles:

RAM estática: flips-flops internos que almacenan información binaria. La información almacenada es válida mientras la unidad está encendida.
RAM dinámica: conjunto de pequeños condensadores que pueden estar cargados o descargados. Debe refrescarse cada pocos milisegundos para impedir la pérdida de información. Tienen mayor capacidad que las estáticas.

Procesador y registros internos


Un registro es una memoria de alta velocidad y poca capacidad, integrada en el microprocesador. Permite guardar transistoriamente 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.

Los registros se dividen en 6 categorías:
*Registros de segmento.
Un registro de segmento se utiliza para alinear en un limite de párrafo o dicho de otra forma codifica la dirección de inicio de cada segmento y su dirección en un registro de segmento supone cuatro bits 0 a su derecha.
Un registro de segmento tiene 16 bits de longitud y facilita un área de memoria para direccionamientos conocidos como el segmento actual. Los registros de segmento son:

Registro CS
Registro DS
Registro SS
Registro ES
Registro FS y GS
Registro CS.
El DOS almacena la dirección inicial del segmento de código de un programa en el registro CS. Esta dirección de segmento, mas un valor de desplazamiento en el registro de apuntado de instrucción (IP), indica la dirección de una instrucción que es buscada para sí ejecución. Para propósito de programación normal, no e necesita referenciar el registro CS.

Registro DS.
La dirección inicial de un segmento de datos de programa es almacenada en el registro DS. En términos sencillos, esta dirección, mas un valor de desplazamiento en una instrucción, genera una referencia a la localidad de un bytes especifico en el segmento de datos.

Registro SS.
El registro SS permite la colocación en memoria de una pila, para almacenamiento temporal de direcciones y datos. El DOS almacena la dirección de inicio del segmento de pila de un programa en el registro SS. Esta dirección de segmento, más un valor de desplazamiento en el registro del apuntador de la pila (SP), indica la palabra actual en la pila que está siendo direccionada. Para propósitos de programación normal, no se necesita referenciar el registro SS.

Registro ES
Algunas operaciones con cadenas de caracteres (datos de caracteres) utilizan el registro esta de segmento para manejar el direccionamiento de memoria. En este contexto, el registro ES esta asociado con el registro DI (índice) . un programa que requiere el uso del registro ES puede inicializarlo con una dirección apropiada.

Registros FS y GS.
Son registros extra de segmento en los procesadores 80386y posteriores a estos procesadores.

*Registros de propósito general.
Los registros de propósito general AX, BX, CX y DX son los caballos de batalla del sistema. Son únicos en el sentido de que se puede direccionarlos como una palabra o como una parte de un byte. El último byte de la izquierda es la parte “alta”, y el último byte de la derecha es la parte “baja”. Por ejemplo, el registro CX consta de una parte CH (alta) y una parte Cl (baja), y usted puede referirse a cualquier parte por su nombre.

Registro AX: El registro AX, el acumulador principal, es utilizado para operaciones que implican entrada/salida y la mayor parte de la aritmética. Por ejemplo, las instrucciones para multiplicar, dividir y traducir suponen el uso del AX. También, algunas operaciones generan código más eficiente si se refieren al AX en lugar de a los otros registros.

Registro BX: El BX es conocido como el registro base ya que es el único registro de propósito general que puede ser índice para direccionamiento indexado. También es común emplear el BX para cálculos.

Registro DX: El DX es conocido como registro de datos. Algunas operaciones de entrada/salida requieren uso, y las operaciones de multiplicación y división con cifras grandes suponen al DX y al AX trabajando juntos.


Registro CX: El CX es conocido como el registro contador. Puede contener un valor para controlar el número de veces que un ciclo se repite o un valor para corrimiento de bits, hacia la derecha o hacia la izquierda. El CX también es usado para muchos cálculos.

*Registros de apuntadores.
Los registros apuntadores están asociados con el registro SS y permiten al procesador accesar datos en el segmento de pila los registros apuntadores son dos:

El registro SP
El registro BP
Registro SP.
El apuntador de pila IP de 16 bits esta asociado con el registro SS y proporciona un valor de desplazamiento que se refiere a la palabra actual que esta siendo procesada en la pila.
El ejemplo siguiente el registro SS contiene la dirección de segmento 27B3[0]H y el SP el desplazamiento 312H Para encontrar la palabra actual que esta siendo procesada en la pila el microprocesador combina las direcciones en el SS y el PP:
Dirección de segmento en el registro SS: 27B30H
Desplazamiento en el registro SP: + 312H

Dirección en la Pila: 27E42H

*Registros de banderas.
Los registros de banderas sirven parar indicar el estado actual de la maquina y el resultado del procesamiento, Cuando algunas instrucciones piden comparaciones o cálculos aritméticos cambian el estado de las banderas.
Las banderas están en el registro de banderas en las siguientes posiciones:
bits 15 14 13 12 11 10 9 8 7 6 5
4 3 2 1
Bandera
Las banderas mas comunes son las siguientes:
OF (Over flow flag, desbordamiento).
Indica el desbordamiento de un bit de orden alto (mas a la izquierda) después de una operación aritmética.
DF (Direction flag, Direccion).
Designa la dirección hacia la izquierda o hacia la derecha para mover o comparar cadenas de caracteres.
IF (Interruption flag, Interrupcion).
Indica que una interrupción externa, como la entrada desde el teclado sea procesada o ignorada.
TF (Trap flag, Trampa).
Examina el efecto de una instrucción sobre los registros y la memoria. Los programas depuradores como DEBUG, activan esta bandera de manera que pueda avanzar en la ejecución de una sola interrupción a un tiempo.
SF (Sign flag, Signo).
Contiene el signo resultante de una operación aritmética (0=positivo y 1= negativo).
ZF (Zero flag, Zero).
Indica el resultado de una operación aritmética o de comparación (0= resultado diferente de cero y 1=resultado igual a cero).
AF (Auxiliary carry flag, Acarreo auxiliar).
Contiene un acarreo externo del bit 3 en un dato de 8 bits, para aritmética especializada
PF (Parity flag, Paridad).
Indica paridad par o impar de una operación en datos de ocho bits de bajo orden (mas a la derecha).
CF (Carry flag, Acarreo).

Contiene el acarreo de orden mas alto (mas a la izquierda) después de una operación aritmética; también lleva el contenido del ultimo bit en una operación de corrimiento o rotación.

*Registros de puntero de instrucción
El registro apuntador de instrucciones (IP) de 16 bits contiene el desplazamiento de dirección de la siguiente instrucción que se ejecuta.
El registro IP esta asociado con el registro CS en el sentido de que el IP indica la instrucción actual dentro del segmento de código que se esta ejecutando actualmente.
En el ejemplo siguiente, el registro CS contiene 25A4[0]H y el IP contiene 412H. Para encontrar la siguiente instrucción que será ejecutada el procesados combina las direcciones en el CS y el IP así:
Segmento de dirección en el registro CS: 25A40H
Desplazamiento de dirección en el registro IP: + 412H
Dirección de la siguiente instrucción: 25E52H




Libreria emu8086.inc

Referencias externas al módulo

Sirve para poder particionar un programa en varios archivos fuentes o módulos. Son imprescindibles si se hace un programa en alto nivel con procedimientos en assembler. Hay tres: PUBLIC, EXTRN e INCLUDE.

PUBLIC nombre[, nombre...]: Estos nombres simbólicos se escriben en el archivo objeto. Durante una sesión con el linker, los símbolos en diferentes módulos pero con los mismos nombres tendrán la misma dirección.

EXTRN nombre:tipo [,nombre:tipo...]: Define una variable externa con el nombre y tipo (NEAR, FAR, BYTE, WORD, DWORD o ABS (número constante especificado con la directiva EQU o =)) especificado. El tipo debe ser el mismo que el del ítem indicado con la directiva PUBLIC en otro módulo.

INCLUDE nombre_de_archivo: Ensambla las sentencias indicadas en dicho archivo.


Para facilitar la programación, hay algunas funciones comunes que pueden incluirse en un programa. Para hacer que nuestros programas usen funciones definidas en otro archivo, debe usar INCLUDE seguido de un nombre de archivo. El compilador busca automáticamente el archivo en la misma carpeta donde se encuentra el archivo de origen, y si no puede encontrar el archivo allí, busca en la carpeta Inc.


Para usar cualquiera de las funciones en emu8086.inc, debe tener la siguiente línea al comienzo de su archivo fuente: include 'emu8086.inc'


emu8086.inc define las siguientes macros entre otros:

PUTC char: imprime un solo caracter
GOTOXY col, row: coloca el cursor en las coordenadas solicitadas
PRINT string: Imprime una cadena
PRINTN string: Imprime una cadena y tras imprimirla hace un salto de linea.

Video mas explicativo y ejemplo:





name "suma de dos numeros"
include "emu8086.inc"
org 100h

.data
suma db 2 dup (?)
.code
sumas proc
    print " Introduce el primer numero: "
    call scan_num
    mov suma[0],cl 
    printn " " 
    print " Introduce el segundo numero: "
    call scan_num
    mov suma[1],cl
    xor ax,ax
    add al,suma[0]
    add al,suma[1]
    printn " "
    print " La suma es: "
    call print_num
sumas endp
exit:
    print " "
    printn " "
    print "Presiona enter para salir..."
    mov ah,0  ;servicio de pulsación de teclado
    int 16h   ;invoca a servicios de taclado
    ret
define_print_string
define_print_num
define_print_num_uns
define_scan_num
end





Libro: Programacion en ensamblador (x86-64)

Aportacion: Brucelee Javier Campos Alv.
Autor: Miquel Albert Orenga y Gerard Enrique Manonellas
Editorial: Universitat Oberta de Cataluya


Programa de Calificaciones

Codigo:

.MODEL SMALL
.STACK 64
.DATA
    MENSAJE1 DB 10,13,"INTRODUZCA UN VALOR (SEGUIDO DE UN ENTER): $" 
    APROBADO DB 10,13,"APROBADO$"
    REPROBADO DB 10,13,"REPROBADO$"
    VAR1 DW ?,'$';DW TIPO DE DATO PARA ALMACENAR CADENAS 
    VAR2 DW ?,'$'                                       
    VAR3 DW ?,'$'
    
.CODE   
OPERACIONES PROC FAR ;DECLARACION DE PROCEDIMIENTO    
    
    MOV AX,@DATA   ;INICIO
    MOV DS,AX
    ;----------------------------------------
    
    ;MUESTRO EL MENSAJE 1
    MOV AH,09; SERVICIO DE IMPRESION DE CADENAS
    MOV DX,OFFSET MENSAJE1
    INT 21H
    
    ;lEO LOS DATOS POR TECLADO    
    ;CARACTER 1
    MOV AH,01 ;SERVICIO DEL TECLADO
    INT 21H
    
    MOV VAR1,AX
    
    ;CARACTER 2   
    MOV AH,01
    INT 21H
    
    ;LECTURA DEL ENTER
    MOV AH,01
    INT 21H  
    
    CMP AL,13   ;CMP COMPRARE     AL==13
    JGE   CONTINUE
    JMP   MAYOR
    
    ;INICIA FUNCIONES
    
   CONTINUE:     ;DECLARACION DE FUNCIONES ETIQUETA_NOMBRE:
        ;OPERACIONES
        MOV AX,VAR1
        CMP AL,037H 
        JGE MAYOR
        JMP MENOR
        
   MAYOR:   
   MOV AH,09
   MOV DX,OFFSET APROBADO 
   INT 21H
   JMP SALIR 
        
   MENOR:   
   MOV AH,09
   MOV DX,OFFSET REPROBADO 
   INT 21H 
   JMP SALIR
    
   SALIR:
   MOV AX,400CH  
   INT 21H
       
OPERACIONES ENDP   
   
END   

;02 IMPRIMIR ALGO DESDE LOS REGISTROS
;09 ALGO GUARDADO EN VARIABLES


Capturas:



Programa Realizar una suma en Lenguaje Ensamblador


Codigo:

.model small
.stack 64  
        ;declaracion de datos
.data
    n1 db 0
    n2 db 0
    suma db 0
    msg1 db "Dame el primer valor:",'$'
    msg2 db 10,13,"Dame el segundo valor:",'$'
    msg3 db 10,13,"Suma=",'$'
        ;declaracion de codigo   
.code
    begin proc far ;Defino un procedimiento
        ;direccionamos al segmentos de datos
        mov ax,@data
        mov ds,ax
        
        ;solicitamos el primer digito
        mov ah,09
        lea dx,msg1
        int 21h
        ;se lee el primer valor
        mov ah,01
        int 21h
        sub al,30h   ;convierte el caracter en numero
        mov n1,al  
        
        ;solicitamos el segundo digio
        mov ah,09
        lea dx,msg2
        int 21h
        ;se lee el segundo valor
        mov ah,01
        int 21h
        sub al,30h   ;convierte el caracter en numero
        mov n2,al 
        
        ;operacion
        mov al,n1
        add al,n2
        add al,30h;convierto a caracter
        mov suma,al 
        mov ah,09
        lea dx,msg3
        int 21h
        
        ; se imprime el caracter con el servicio 02 de la interrupcion 21h
        mov ah,02
        mov dl,suma
        int 21h
        mov ah,4ch  ;Devuelve el control al equipo
        int 21h
        Begin endp ;especifico el termino del procedimiento
        end         ;especifico el final del bloque de codigo





lunes, 11 de febrero de 2019

Programa Resta en emu8086


Codigo:


.MODEL SMALL
.STACK 64
.DATA
N1 DB 0
N2 DB 0
RESTA DB 0
MSG1 DB "DAME EL PRIMER VALOR: " , "$"
MSG2 DB 10,13, "DAME EL SEGUNDO VALOR: " , "$"
MSG3 DB 10,13, "RESTA= " , "$"
.CODE
BEGIN PROC FAR
;DIRECCIONAMOS AL SEGMENTOS DE DATOS
MOV AX, @DATA
MOV DS, AX
;SOLICITAMOS EL PRIMER DIGITO
MOV AH, 09
LEA DX, MSG1
INT 21H
MOV AH, 01
INT 21H
SUB AL, 30H;CONVIERTE EL CARACTER EN NUMERO
MOV N1, AL
;SOLICITAMOS EL SEGUNDO DIGITO
MOV AH, 09
LEA DX, MSG2
INT 21H
MOV AH, 01
INT 21H
SUB AL, 30H;CONVIERTE EL CARACTER EN NUMERO
MOV N2, AL
;OPERACION
MOV AL, N1
SUB AL, N2
ADD AL, 30H;CONVIERTE A CARACTER
MOV RESTA, AL
MOV AH, 09
LEA DX, MSG3
INT 21H
;SE IMPRIME EL CARACTER CON EL SERVICIO 02 DE LA INT 21H
MOV AH, 02
MOV DL, RESTA
INT 21H
MOV AH, 4CH
INT 21
BEGIN ENDP
END

x

Lista de Interrupciones para procesador 8086 de Lenguaje Ensamblador





Practica 2: Hola mundo 2.0- Interrupcion 16H







Codigo:


.CODE SEGMENT
ASSUME CS:CODE, DS:CODE, SS:CODE. ES:CODE
ORG 100h
principio:
mov ah,0Fh
mov ah,0
int 10h
lea dx, mensaje_a_mostrar
mov ah,9h
int 21h
int 20h
mensaje_a_mostrar db "hola mundo!$",0
CODE ENDS


Interrupcion 16H




Codigo:


.MODEL SMALL
.STACK
.DATA
CADENA1 DB 'HOLAMUNDO $'
CADENA2 DB 'HOLAMUNDO2 $'
.CODE
PROGRAMA:
MOV AX,@DATA
MOV DS,AX
MOV DX,OFFSET CADENA1
MOV AH,9
INT 21H
MOV DX,OFFSET CADENA2
MOV AH,9
INT 21H
MOV AX,0
INT 16H
END PROGRAMA


Practica 1: Hola mundo en Lenguaje Ensamblador




Codigo:


.MODEL SMALL
.STACK
.DATA
CADENA1 DB 'HOLAMUNDO $'
CADENA2 DB 'HOLAMUNDO2 $'
.CODE
PROGRAMA:
MOV AX,@DATA
MOV DS,AX
MOV DX,OFFSET CADENA1
MOV AH,9
INT 21H
MOV DX,OFFSET CADENA2
MOV AH,9
INT 21H
END PROGRAMA

Turbo Assembler



Codigo:


.MODEL SMALL
.STACK
.DATA
CADENA1 DB 'HOLAMUNDO $'
CADENA2 DB 'HOLAMUNDO2 $'
.CODE
PROGRAMA:
MOV AX,@DATA
MOV DS,AX
MOV DX,OFFSET CADENA1
MOV AH,9
INT 21H
MOV DX,OFFSET CADENA2
MOV AH,9
INT 21H
END PROGRAMA

Lenguaje Ensamblador

                                          Resultado de imagen para lenguaje ensamblador

El lenguaje ensamblador es el lenguaje de programación utilizado para escribir programas informáticos de bajo nivel, y constituye la representación más directa del Código máquinaespecífico para cada arquitectura de computadoras legible por un programador. Aun hoy se utiliza en la programación de handler o manipuladores de dispositivos de hardware.


Características

El código escrito en lenguaje ensamblador posee una cierta dificultad de ser entendido directamente por un ser humano ya que su estructura se acerca más bien al lenguaje máquina, es decir, lenguaje de bajo nivel.
El lenguaje ensamblador es difícilmente portable, es decir, un código escrito para un Microprocesador, suele necesitar ser modificado, muchas veces en su totalidad para poder ser usado en otra máquina distinta, aun con el mismo Microprocesador, solo pueden ser reutilizados secciones especiales del código programado.
Los programas hechos en lenguaje ensamblador, al ser programado directamente sobre Hardware, son generalmente más rápidos y consumen menos recursos del sistema (memoria RAM y ROM). Al programar cuidadosamente en lenguaje ensamblador se pueden crear programas que se ejecutan más rápidamente y ocupan menos espacio que con lenguajes de alto nivel. 
Con el lenguaje ensamblador se tiene un control muy preciso de las tareas realizadas por un Microprocesador por lo que se pueden crear segmentos de código difíciles de programar en un lenguaje de alto nivel.
También se puede controlar el tiempo en que tarda una Rutina en ejecutarse, e impedir que se interrumpa durante su ejecución.
El lenguaje ensamblador es un código estructurado y gravitatorio desarrollado sobre un archivo de programación (.ASM), en el cual pueden existir varios programas, macros o rutinas que pueden ser llamados entre si.


Lenguaje

Un programa escrito en lenguaje ensamblador consiste en una serie de Instrucciones que corresponden al flujo de órdenes ejecutables que pueden ser cargadas en la Memoria de un sistema basado en Microprocesador. Por ejemplo, un Procesador x86 puede ejecutar la siguiente instrucción Binaria como se expresa en código de máquina: 

Binario: 10110000 01100001 (Hexadecimal: 0xb061) 


La representación equivalente en lenguaje ensamblador es más fácil de recordar:
MOV al, 061h


Esta instrucción significa:
Asigna el valor Hexadecimal 61 (97 Decimal) al registro "al".


El mnemónico "mov" es un código de operación u "opcode", elegido por los diseñadores de la colección de instrucciones para abreviar "move" (mover, pero en el sentido de copiar valores de un sitio a otro). El opcode es seguido por una lista de argumentos o parámetros, completando una instrucción de ensamblador típica. A diferencia de los lenguajes de alto nivel, aquí hay usualmente una correspondencia 1 a 1 entre las instrucciones simples del ensamblador y el lenguaje de máquina. Sin embargo, en algunos casos, un ensamblador puede proveer "pseudo instrucciones" que se expanden en un código de máquina más extenso a fin de proveer la funcionalidad necesaria. Por ejemplo, para un código máquina condicional como "si X mayor o igual que", un ensamblador puede utilizar una pseudo instrucción al grupo "haga si menor que", y "si = 0" sobre el resultado de la condición anterior. Los Ensambladores más completos también proveen un rico lenguaje de macros que se utiliza para generar código más complejo y secuencias de datos. Cada arquitectura de microprocesadores tiene su propio lenguaje de máquina, y en consecuencia su propio lenguaje ensamblador ya que este se encuentra muy ligado al la estructura del hardware para el cual se programa. Los microprocesadores difieren en el tipo y número de operaciones que soportan; también pueden tener diferente cantidad de registros, y distinta representación de los tipos de datos en memoria. Aunque la mayoría de los microprocesadores son capaces de cumplir esencialmente las mismas funciones, la forma en que lo hacen difiere y los respectivos lenguajes ensamblador reflejan tal diferencia. Pueden existir múltiples conjuntos de mnemónicos o Sintaxis de lenguaje ensamblador para un mismo conjunto de instrucciones, instanciados típicamente en diferentes programas en ensamblador. En estos casos, la alternativa más popular es la provista por los fabricantes, y usada en los manuales del programa.
Lenguajes Ensambladores:
Sin importar varias caracteristicas a favor de los lenguajes de este tipo no son muy utilizados actualmente por la comunidad de programadores, esto debido al tiempo que toma en desarrollar algun sistema en estos lenguajes. Por poner un ejemplo, el desarrollo de un sistema operativo escrito en C, que por lo regular tomaria 1 año por decir algo, en ensamblador tomaría 20 años. Actualmente en palabras de Fernando Zorrilla Autor del blog Quora menciona "La programación en lenguaje assembler es útil en algunas áreas, especialmente en lo que es protección y desprotección de aplicaciones y en la construcción particular de drivers customizados."

ARB assembly language
Autocoder
COMPASS
Cross assembler
MACRO-11
MACRO-10
Macro assembler
IBM Basic assembly language
MC7 (computing)
X86 assembly language