Lenguaje ensamblador
El lenguaje
ensamblador es un lenguaje de
programación de bajo nivel para microprocesadores y microcontroladores.
Tomado de mastermagacine |
Implementa una representación simbólica del códigos de máquina binario y otras constantes necesarias para programar una arquitectura dada de la CPU y consiste en la representación más directa del código máquina específico para cada arquitectura legible por un programador.
Está basada en mnemónicos que simbolizan las instrucciones, registros del procesador, y posiciones de
memoria.
El ensamblador realiza
una traducción más o menos isomorfa desde las sentencias mnemónicas a las instrucciones
y datos de máquina.
Actualmente se utiliza cuando se requiere la manipulación directa del hardware, alto rendimiento, o
un uso de recursos controlado y reducido,
controladores de dispositivo y en
el desarrollo de sistemas operativos.
Características
El lenguaje ensamblador
no suele ser portable, en otras palabras, el
código para un microprocesador no sirve para ejecutarse en otro (modelo
o marca diferentes) por lo que es necesario modificarlo para usarlo en otro microprocesador de diferente
modelo o arquitectura diferentes. En estos casos el código debe reescribirse.
El lenguaje ensamblador
permite controlar exactamente las tareas realizadas por el microprocesador y es
capaz de crear código imposible de imitar en un lenguaje de alto nivel, ya que
el lenguaje ensamblador dispone de instrucciones que no están disponibles en
los lenguajes de alto nivel.
Programas ensambladores
Son programas que
traducen desde el lenguaje nemónico ensamblador al código máquina real de ceros
y unos que realmente se almacena en la memoria del microprocesador.
No hay que confundirlos
con el lenguaje en ensamblador que es un lenguaje sencillo creado para no
programar directamente en código máquina. Son programas que permiten escribir
directamente los nemónicos y nos evita teclear los códigos correspondientes a
cada instrucción.
Han estado disponibles
desde los años 1950. Los ensambladores modernos, optimizan la planificación de
instrucciones para explotar la CPU de forma eficiente.
Hay dos tipos de
lenguaje ensamblador dependiendo de los pasos que pasan a través del código
fuente.
• Los de un paso pasan
a través del código fuente una vez y asumen que todos los símbolos se definirán
antes de cualquier instrucción que los refiera.
• Los de dos pasos crean una tabla con todos los símbolos y
sus valores en el primer paso, después en un segundo paso utilizan la tabla
para generar el código definitivo. En el primer paso se debe por lo menos poder
determinar la longitud de cada instrucción para que se posible calcular las
direcciones de los símbolos.
Un lenguaje ensamblador
de un solo paso es más rápido mientras
que un ensamblador de dos pasos permite
al programa ser definido de manera más lógica de modo que será más fácil de
programar y de leer.
La palabra ensamblador
se utiliza para referirse al lenguaje ensamblador y también al programa ensamblador.
Operaciones
Las instrucciones de la
CPU pueden agruparse, según su funcionalidad, en:
Operaciones con enteros:
(de 8, 16, 32 y 64 bits dependiendo de la arquitectura de la CPU,
Estas son las
operaciones que realiza la ALU (enlace a Arquitectura Básica) de la CPU
• Operaciones aritméticas.
• Operaciones booleanas.
• Operaciones de bits.
• Comparaciones
Operaciones de
movimiento de 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 una dirección de memoria
• desde una dirección
de memoria a un registro
• desde una dirección de memoria a otra
• asignar un valor inmediato a un registro
• asignar un valor inmediato a una dirección de memoria
Operaciones de pila:
La pila es una serie de
posiciones de memoria especiales donde los datos se almacenan como en una caja.
El primer dato en entrar será el último en ser leído mientras que el último
dato en entrar será el primero en ser leído. Por eso se llama pila y su almacenamiento
es de tipo LIFO (Last Input, First Output)
• PUSH escribe datos en la pila.
• POP lee datos de la pila
Operaciones
de entrada/salida:
Son operaciones que
mueven datos de un registro o desde la memoria hacia un puerto o viceversa.
• INPUT Lectura desde un puerto de entrada
• OUTPUT Escritura hacia un puerto de salida
Operaciones para el control del flujo del programa:
Saltos condicionales de
acuerdo con el resultado de operaciones
de comparación
Saltos incondicionales
Llamadas y retornos de
interrupciones
Llamadas y retornos de
subrutinas
Operaciones con números reales:
La ALU de una CPU sólo
puede sumar, aun así diferentes secuencias de instrucciones así como la
utilización de diferentes códigos y bits de acarreo y signo permiten realizar
las operaciones aritméticas básicas y otras más complejas.
Una CPU puede tener
operaciones de punto flotante con números reales a través de un coprocesador
numérico.
Operaciones matemáticas:
Operaciones aritméticas.
Suma, resta, multiplicación, división, cambio de signo, valor absoluto, parte
entera
Operaciones trigonométricas.
Operaciones con logaritmos, potencias y raíces.
Lenguaje máquina
El lenguaje ensamblador
utiliza mnemónicos para cada una de las instrucciones de la CPU. Aun así su programación
no es sencilla pues es necesario conocer a fondo la arquitectura física del
microprocesador para poder programarlo eficientemente.
Por ejemplo, en un
lenguaje una sentencia del tipo:
MOVER RB, 45H
Asigna el valor
hexadecimal 45 (69 en decimal) al
registro B.
El programa ensamblador lee la sentencia de arriba y produce su equivalente binario en lenguaje de máquina, en este caso es una instrucción de dos palabras, la primera palabra estará codificada en el juego de instrucciones del microprocesador, se trata de una codificación arbitraria en la que la instrucción MOVER RB Hx puede estar codificada como 1F (por ejemplo) y la segunda palabra sería el valor propiamente dicho, en este caso el 45 de modo que tendríamos:
Binario: 00011111
(1F) 010010101 (45) (hexadecimal: 1F 45)
El mnemónico MOVER (MOV
en Inglés) es un código de operación u opcode. Como acabo de indicar el opcode
es seguido por la lista de argumentos o parámetros, (en este caso uno)
completando la instrucción de ensamblador. En el ejemplo, RB es un registro de 8 bits del procesador, al
cual le asignaremos el valor hexadecimal 45 tal y como se ha indicado.
Por tanto el código de
máquina que genera el ensamblador estará
formado por 2 bytes. El primero
contendrá la instrucción MOVER (codificada arbitrariamente) y el segundo
contendrá el valor introducido 45.
Dicha instrucción
binaria 00011111 010010101 será
interpretada directamente por el procesador el cual al final del ciclo habrá
introducido el valor 01000101 en el registro RB.
Macros
Una macro en ensamblador
es una secuencia de instrucciones. Una vez un macro ha sido definido, su nombre
puede ser usado en lugar de un mnemónico. Cuando el ensamblador procesa la
macro, reemplaza la sentencia por las líneas del texto asociadas a ese macro,
entonces las procesa como si hubieran existido en el archivo del código fuente
original. Es decir una macro en ensamblador es una subrutina, es decir un
programa corto escrito previamente y almacenado en un lugar específico de la
memoria el cual es llamado cada vez que se invoca la macro.
Las macros suelen
nombrarse con etiquetas cortas que las definen y hacen que los programas en
lenguaje ensamblador parezcan mucho más cortos, requiriendo menos líneas de
código fuente, igual que en los lenguajes de alto nivel.
Aunque el lenguaje
ensamblador es casi siempre manejado y generado por compiladores, todavía se
utiliza manipular directamente el hardware, obtener acceso a instrucciones
especializadas del procesador, o para resolver problemas de desempeño crítico.
Uso actual
La complejidad de los
procesadores actuales hace la optimización cada vez más difícil para los
compiladores, además las prestaciones cada vez mayores de los procesadores
hacen que la mayoría de las CPU permanezcan desocupadas la mayor parte del
tiempo. Esto hace que la velocidad de ejecución de código no sea ya un
problema.
El lenguaje ensamblador se utiliza principalmente para traducir lenguajes de alto nivel en código máquina, o para funciones críticas o en procesos industriales, sobre todo si es importante el tiempo real.
También se utiliza si se
necesita un ejecutable independiente (stand-alone) que deba ejecutarse sin
recursos. Son programas empotrados que solo disponen de una pequeña cantidad de
memoria y está dirigido para hacer tareas con propósito simple, por ejemplo en
teléfonos, sistemas de ignición de combustible para automóviles, control de
aire acondicionado, sensores y sistemas
de seguridad.
O cuando se necesitan utilizar instrucciones específicas del procesador no disponibles por el compilador. Un ejemplo es la instrucción de rotación de bits que se utiliza en algoritmos de cifrado.
El lenguaje ensamblador
es todavía enseñado en los programas de ciencias de la computación y en
ingeniería electrónica. Aunque pocos programadores trabajan regularmente con el
lenguaje directamente, este es muy útil para estudiar conceptos fundamentales,
como aritmética binaria, asignación de memoria, procesamiento del stack,
procesamiento de interrupciones, y diseño de compiladores.
La mayoría de los
computadores modernos tienen un conjunto de instrucciones similares. Con lo que
estudiar un solo lenguaje ensamblador es suficiente para aprender.
Lenguajes de nivel medio
como C, proveen sintaxis especial para empotrar lenguaje ensamblador en la plataforma
hardware.
El lenguaje ensamblador
también es valioso para hacer ingeniería inversa, pues muchos programas son
distribuidos exclusivamente como código de máquina. El código de máquina es
fácil de trasladar hacia lenguaje ensamblador para luego ser examinado en esta
forma, aunque sigue siendo muy difícil trasladarlo a un lenguaje de alto nivel.
También existen herramientas para hacer esto último de forma automática.
No hay comentarios:
Publicar un comentario