.

lunes, 18 de noviembre de 2013

Tipos de Ensambladores



  
El término ensamblador (del inglés assembler) se refiere a un tipo de programa informático que se encarga de traducir un fichero fuente escrito en un lenguaje ensamblador, a un fichero objeto que contiene código máquina, ejecutable directamente por el microprocesador.


Funcionamiento
El programa lee el fichero escrito en lenguaje ensamblador y sustituye cada uno de los códigos nemotécnicos que aparecen por su código de operación correspondiente en sistema binario para la plataforma que se eligió como destino en las opciones específicas del ensamblador.
Tipos de ensambladores
Podemos distinguir entre dos tipos de ensambladores:
•             Ensambladores básicos. Son de muy bajo nivel, y su tarea consiste básicamente en ofrecer nombres simbólicos a las distintas instrucciones, parámetros y cosas tales como los modos.

•             Ensambladores modulares 32-bits o de alto nivel. Son ensambladores que aparecieron como respuesta a una nueva arquitectura de procesadores de 32 bits, muchos de ellos teniendo compatibilidad hacia atrás pudiendo trabajar con programas con estructuras de 16 bits. Además de realizar la misma tarea que los anteriores, permitiendo también el uso de macros, permiten utilizar estructuras de programación más complejas propias de los lenguajes de alto nivel.




Lenguaje ensamblador
El lenguaje ensamblador, o assembler (assembly language en inglés), es un lenguaje de programación de bajo nivel para los computadores, microprocesadores, micro controladores y otros circuitos integrados programables. Implementa una representación simbólica de los máquina binarios y otras constantes necesarias para programar una arquitectura dada de CPU y constituye la representación más directa del código máquina específico para cada arquitectura legible por un programador. Esta representación es usualmente definida por el fabricante de hardware, y está basada en los mnemónicos que simbolizan los pasos de procesamiento (las instrucciones), los registros del procesador, las posiciones de memoria y otras características del lenguaje. Un lenguaje ensamblador es por lo tanto específico de cierta arquitectura de computador física (o virtual). Esto está en contraste con la mayoría de los lenguajes de programación de alto nivel, que idealmente son portátiles.
Un programa utilitario llamado ensamblador es usado para traducir sentencias del lenguaje ensamblador al código de máquina del computador objetivo. El ensamblador realiza una traducción más o menos isomorfa (un mapeo de uno a uno) desde las sentencias mnemónicas a las instrucciones y datos de máquina. Esto está en contraste con los lenguajes de alto nivel, en los cuales una sola declaración generalmente da lugar a muchas instrucciones de máquina.
Muchos sofisticados ensambladores ofrecen mecanismos adicionales para facilitar el desarrollo del programa, controlar el proceso de ensamblaje, y la ayuda de depuración. Particularmente, la mayoría de los ensambladores modernos incluyen una facilidad de macro (descrita más abajo), y son llamados macro ensambladores.
Fue usado principalmente en los inicios del desarrollo de software, cuando aún no se contaba con potentes lenguajes de alto nivel y los recursos eran limitados. Actualmente se utiliza con frecuencia en ambientes académicos y de investigación, especialmente cuando se requiere la manipulación directa de hardware, alto rendimiento, o un uso de recursos controlado y reducido.




Características
•             El código escrito en lenguaje ensamblador posee una cierta dificultad de ser entendido ya que su estructura se acerca al lenguaje máquina, es decir, es un lenguaje de bajo nivel.
•             El lenguaje ensamblador es difícilmente portable, es decir, un código escrito para un microprocesador, puede necesitar ser modificado, para poder ser usado en otra máquina distinta. Al cambiar a una máquina con arquitectura diferente, generalmente es necesario reescribirlo completamente.
•             Los programas hechos por un programador experto en lenguaje ensamblador son generalmente mucho más rápidos y consumen menos recursos del sistema (memoria RAM y ROM) que el programa equivalente compilado desde un lenguaje de alto nivel. 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 y/o muy ineficientes de programar en un lenguaje de alto nivel, ya que, entre otras cosas, en el lenguaje ensamblador se dispone de instrucciones del CPU que generalmente no están disponibles en los lenguajes 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.


Programa ensamblador
Típicamente, un programa ensamblador (assembler en inglés) moderno crea código objeto traduciendo instrucciones mnemónicas de lenguaje ensamblador en opcodes, y resolviendo los nombres simbólicos para las localizaciones de memoria y otras entidades.1 El uso de referencias simbólicas es una característica clave del lenguaje ensamblador, evitando tediosos cálculos y actualizaciones manuales de las direcciones después de cada modificación del programa. La mayoría de los ensambladores también incluyen facilidades de macros para realizar sustitución textual - ej. generar cortas secuencias de instrucciones como expansión en línea en vez de llamar a subrutinas.
Los ensambladores son generalmente más simples de escribir que los compiladores para los lenguajes de alto nivel, y han estado disponibles desde los años 1950. Los ensambladores modernos, especialmente para las arquitecturas basadas en RISC, tales como MIPS, Sun SPARC, y HP PA-RISC, así como también para el x86 (-64), optimizan la planificación de instrucciones para explotar la segmentación del CPU eficientemente.
En los compiladores para lenguajes de alto nivel, son el último paso antes de generar el código ejecutable.


Número de pasos
Hay dos tipos de ensambladores basados en cuántos pasos a través de la fuente son necesarios para producir el programa ejecutable.
•             Los ensambladores de un solo paso pasan a través del código fuente una vez y asumen que todos los símbolos serán definidos antes de cualquier instrucción que los refiera.
•             Los ensambladores de dos pasos crean una tabla con todos los símbolos y sus valores en el primer paso, después usan la tabla en un segundo paso para generar código. El ensamblador debe por lo menos poder determinar la longitud de cada instrucción en el primer paso para que puedan ser calculadas las direcciones de los símbolos.
La ventaja de un ensamblador de un solo paso es la velocidad, que no es tan importante como lo fue en un momento dados los avances en velocidad y capacidades del computador. La ventaja del ensamblador de dos pasos es que los símbolos pueden ser definidos dondequiera en el código fuente del programa. Esto permite a los programas ser definidos de maneras más lógicas y más significativas, haciendo los programas de ensamblador de dos paso más fáciles leer y mantener.
Ensambladores de alto nivel
Los más sofisticados ensambladores de alto nivel proporcionan abstracciones del lenguaje tales como:
•             Estructuras de control avanzadas
•             Declaraciones e invocaciones de procedimientos/funciones de alto nivel
•             Tipos de datos abstractos de alto nivel, incluyendo las estructuras/records, uniones, clases, y conjuntos
•             Procesamiento de macros sofisticado (aunque está disponible en los ensambladores ordinarios desde finales 1960 para el IBM/360, entre otras máquinas)
•             Características de programación orientada a objetos



Uso del término
Note que, en el uso profesional normal, el término ensamblador es frecuentemente usado tanto para referirse al lenguaje ensamblador como también al programa ensamblador (que convierte el código fuente escrito en el lenguaje ensamblador a código objeto que luego será enlazado para producir lenguaje de máquina). Las dos expresiones siguientes utilizan el término "ensamblador":
•             "El CP/CMS fue escrito en ensamblador del IBM S/360"
•             "El ASM-H fue un ensamblador del S/370 ampliamente usado"
La primera se refiere al lenguaje y la segundo se refiere al programa.



INSTRUCCIONES DE CPU
La mayoría de las CPU tienen más o menos los mismos grupos de instrucciones, aunque no necesariamente tienen todas las instrucciones de cada grupo. Las operaciones que se pueden realizar varían de una CPU a otra. Una CPU particular puede tener instrucciones que no tenga otro y viceversa. Los primeros microprocesadores de 8 bits no tenían operaciones para multiplicar o dividir números, por ejemplo, y había que hacer subrutinas para realizar esas operaciones. Otras CPU puede que no tengan operaciones de punto flotante y habría que hacer o conseguir bibliotecas que realicen esas operaciones.
Las instrucciones de la CPU pueden agruparse, de acuerdo a su funcionalidad, en:
Operaciones con enteros: (de 8, 16, 32 y 64 bits dependiendo de la arquitectura de la CPU, en los sistemas muy viejos también de 12, 18, 24, 36 y 48 bits)
Estas son operaciones realizadas por la Unidad aritmético lógica de la CPU
• Operaciones aritméticas. Como suma, resta, multiplicación, división, módulo, cambio de signo
• Operaciones booleanas. Operaciones lógicas bit a bit como AND, OR, XOR, NOT
• Operaciones de bits. Como desplazamiento y rotaciones de bits (hacia la derecha o hacia la izquierda, a través del bit del acarreo o sin él)
• Comparaciones



Operaciones de mover datos:
Entre los registros y la memoria:
Aunque la instrucción se llama "mover", en la CPU, "mover datos" significa en realidad copiar datos, desde un origen a un destino, sin que el dato desaparezca del origen.
Se pueden mover valores:
•             desde un registro a otro
•             desde un registro a un lugar de la memoria
•             desde un lugar de la memoria a un registro
•             desde un lugar a otro de la memoria
•             un valor inmediato a un registro
•             un valor inmediato a un lugar de memoria
Operaciones de stack:
•             PUSH (escribe datos hacia el tope del stack)
•             POP (lee datos desde el tope del stack)
Operaciones de entrada/salida:
Son operaciones que mueven datos de un registro, desde y hacia un puerto; o de la memoria, desde y hacia un puerto
•             INPUT Lectura desde un puerto de entrada
•             OUTPUT Escritura hacia un puerto de salida.
Operaciones para el control del flujo del programa:
•             Llamadas y retornos de subrutinas
•             Llamadas y retornos de interrupciones
•             Saltos condicionales de acuerdo al resultado de la comparaciones
•             Saltos incondicionales



Operaciones con números reales:
El estándar para las operaciones con números reales en las CPU está definido por el IEEE 754.
Una CPU puede tener operaciones de punto flotante con números reales mediante el coprocesador numérico (si lo hay), como las siguientes:
•             Operaciones aritméticas. Suma, resta, multiplicación, división, cambio de signo, valor absoluto, parte entera
•             Operaciones trascendentales



Diseño del lenguaje y Elementos básicos
Hay un grado grande de diversidad en la manera en que los autores de los ensambladores categorizan las sentencias y en la nomenclatura que usan. En particular, algunos describen cualquier cosa como pseudo-operación (pseudo-Op), con excepción del mnemónico de máquina o del mnemónico extendido.
Un típico lenguaje ensamblador consiste en 3 tipos de sentencias de instrucción que son usadas para definir las operaciones del programa:
•             Mnemónicos de opcode
•             Secciones de datos
•             Directivas de ensamblador
Mnemónicos de opcode y mnemónicos extendidos
A diferencia de las instrucciones (sentencias) de los lenguajes de alto nivel, instrucciones en el lenguaje ensamblador son generalmente muy simples. Generalmente, una mnemónico es un nombre simbólico para una sola instrucción en lenguaje de máquina ejecutable (un opcode), y hay por lo menos un mnemónico de opcode definido para cada instrucción en lenguaje de máquina. Cada instrucción consiste típicamente en una operación u opcode más cero o más operandos. La mayoría de las instrucciones refieren a un solo valor, o a un par de valores. Los operandos pueden ser inmediatos (típicamente valores de un byte, codificados en la propia instrucción), registros especificados en la instrucción, implícitos o las direcciones de los datos localizados en otra parte de la memoria. Esto está determinado por la arquitectura subyacente del procesador, el ensamblador simplemente refleja cómo trabaja esta arquitectura. Los mnemónicos extendidos son frecuentemente usados para especificar una combinación de un opcode con un operando específico, ej, el ensamblador del System/360 usa a B como un mnemónico extendido para el BC con una máscara de 15 y NOP al BC con una máscara de 0.