El lenguaje ensamblador

Como sabemos, el único lenguaje que son capaces de entender los microcontroladores es el llamado “Código máquina”, el cual se encuentra formado por los ceros y unos del sistema binario. Esto por supuesto dificulta mucho, o imposibilita mejor dicho, la tarea de programar estos procesadores. Por este motivo existen los lenguajes ensambladores, mediante los cuales el programador puede hacer su tarea gracias a que se trata de un lenguaje con el cual se puede expresar con más naturalidad, pero que a su vez puede ser “entendido” por el microprocesador que se está programando.

Los lenguajes ensambladores llevan mucho tiempo entre nosotros, y aunque en la actualidad existan lenguajes de programación de alto nivel, todavía se sigue utilizando el lenguaje ensamblador para la programación de dispositivos, controladores de hardware y mucho más. Es por ello que en este artículo conoceremos todo acerca de los lenguajes ensambladores, desde sus comienzos hasta sus aplicaciones actuales, siempre con de manera clara y precisa para poder ser entendidos por todos, independientemente de su nivel de conocimientos en estos temas.

Pero antes de meternos de lleno en el tema de los lenguajes ensambladores, una de las mejores ideas que podemos tener es refrescarnos la memoria acerca de los fundamentos de los lenguajes de programación, así como de algunas otras áreas relacionadas con ello.

Índice de Contenidos()

    ¿Qué es un lenguaje de programación?

    De manera sencilla clara, podríamos decir que un lenguaje de programación es un conjunto de símbolos, palabras clave, códigos y reglas semánticas que son utilizados para crear una secuencia o serie de instrucciones algorítmicas, las cuales serán utilizadas para crear un programa que pueda controlar el comportamiento tanto físico como lógico de la computadora, con el objetivo de obtener un determinado resultado.

    Podría definirse en muy pocas palabras que el lenguaje de programación es un sistema estructurado de comunicación que permite el nexo entre el programador y el dispositivo que está programando.

    En este punto, es fundamental saber cómo es qué funciona un lenguaje de programación, ya que todos los dispositivos electrónicos de la actualidad necesitan ser programados a través de un lenguaje de programación para poder llevar a cabo su tarea. Desde un televisor Smart TV hasta un lavarropas.

    El lenguaje de programación es estos casos, y en muchos más, es utilizado para que el programador pueda comunicarse con el hardware o el software del equipo y proporcionarle los aspectos básicos y avanzados de su comportamiento, como por ejemplo con cuáles datos debe operar, cómo deben ser almacenados, transmitidos o tratados esos datos y finalmente la acción que debe tomar el software o hardware con estos datos dependiendo de las diferentes variables que se hayan impuesto.

    Después de leer estos párrafos, seguramente te ingresarará saber: Que es programar en informática? sigue este link para entenderlo

    ¿Qué tipos de lenguaje de programación existen?

    Como hemos establecido, el lenguaje de programación es el elemento clave de la tecnología que le permite al programador darle vida a los programas y sistemas operativos y software de múltiples dispositivos. Estos lenguajes de programación en la actualidad se clasifican en dos tipos bien diferenciados, lenguaje de bajo nivel y de alto nivel, sin embargo, existen otros que complementan o expanden las capacidades de los mencionados.

    Cabe destacar en este punto que todos los programas deben ser programados mediante algoritmos, siendo una de las principales herramientas para ayudarnos con este tema Pseint, el del cual hablamos en mucha más profundidad en este artículo.

    Lenguaje máquina

    El llamado “Lenguaje máquina” es uno de los lenguajes más viejos que existen; se forma mediante la combinación de “1” y “0”, es decir que es un lenguaje que sólo usa el sistema binario. Esto es así debido a que este es el único sistema que los dispositivos y computadoras son capaces de interpretar.

    Lenguaje de programación de bajo nivel

    La función básica de este lenguaje de programación es la de actuar a modo de interfaz entre el hardware y el software de un determinado dispositivo.

    Lenguaje ensamblador

    El lenguaje sobre el cual estamos profundizando en este artículo. El lenguaje ensamblador fue el primer intento en la búsqueda de un sustituto más sencillo de comunicarse de forma directa con el hardware de un dispositivo. Este tipo de lenguajes actúan como conversores, ya que los dispositivos utilizan el lenguaje binario, y el programador un lenguaje de programación más flexible y sencillo de usar, llamado lenguaje de alto nivel.

    Lenguaje de programación de alto nivel

    El objetivo principal del lenguaje de alto nivel es el de hacer las cosas más fáciles para el programador, ya que las instrucciones que puede utilizar para crear los programas se presentan de una manera mucho más entendible.

    Si quieres saber más acerca de herramientas de programación como por ejemplo el pseudocódigo, lo mejor que podemos hacer es pulsar sobre este enlace, en donde encontraremos mucha información sobre el tema, además de unos buenos ejemplos de cómo se utiliza.

    Historia y presente del lenguaje ensamblador

    El lenguaje ensamblador ha sido parte de la historia de la informática desde los inicios de la misma, y podría tomarse como la primera interacción en el año 1949, cuando fue desarrollada EDSAC, siglas en inglés de “Electronic Delay Storage Automatic Calculator”, que en español significa “Calculadora Automática de Almacenamiento con Retardo Electrónico”, la primera computadora en incorporar órdenes internas. Como dato de color podemos decir que OXO, el primer videojuego de la historia, fue desarrollador específicamente para poder ser ejecutado en esta computadora.

    Entre las características más destacadas de EDSAC, se puede mencionar que contaba con el primer ensamblador del mundo, muy primitivo, el cual aprovechaba el diseño mnemotécnico de la computadora. El primero de muchos ejercicios llevados a cabo por este primer lenguaje ensamblador fue un programa de números cuadrados, el que se corrió en EDSAC el 6 de mayo de 1949, y que utilizaba nemotécnicos, desarrollado por Beatrice Worsley.

    El segundo gran paso en la historia de los ensambladores se dio cuando Stan Poley desarrolló en el año 1954 SOAP, siglas del inglés que significan “Symbolic Optimal Assembly Program”, y que en español se puede traducir como “Programa de Ensamblaje Óptimo Simbólico”.

    Este ensamblador fue desarrollado en las instalaciones IBM Thomas J. Watson Research Center específicamente para la computadora IBM 650 Magnetic Drum Data-Processing Machine. SOAP era un ensamblador de pasos múltiples, lo que significa que es capaz de procesar el programa más de una vez para generar el programa de objetos.

    Tras la implementación de estos primeros lenguajes ensambladores, su éxito fue creciendo de manera exponencial, ya que ofrecía muchas ventajas, sobre todo a los técnicos en programación de la época, que podían desligarse de ciertas tareas como la de recordar largas secuencias de números y códigos, además ofrecían un tamaño mínimo, algo fundamental en aquellos tiempos de las primeras computadoras comerciales, alta velocidad, y sobre todo una probada y eficaz confiabilidad, aunque también pueda deberse a la falta de compiladores de lenguaje de alto nivel diseñados específicamente para poder ser utilizados en este tipo de microcomputadores.

    A partir de esto, muchas aplicaciones comerciales se comenzaron a desarrollar utilizando lenguajes ensambladores, y muchas microcomputadoras dependían de forma inseparable de lenguajes ensambladores para poder operar estos programas con su hardware, como por ejemplo IBM PC DOS o Lotus 1-2-3, o hasta incluso apps mucho más modernas como algunos juegos en la década de 1990. En este sentido, la mayor parte de las computadoras desarrolladas entre las décadas de 1980 y 1990, como por ejemplo las Atari y las MSX estaban atadas al uso de un lenguaje ensamblador.

    Sin embargo, todo esto iba a cambiar severamente con la aparición de los llamados lenguajes de alto nivel, los cuales gracias a su amplio abanico de opciones y características lograron que para la década de 1980 el uso de los lenguajes ensambladores se redujera drásticamente.

    Si bien su uso se ha visto reducido, lo cierto es que en la actualidad, el lenguaje ensamblador todavía es ampliamente utilizado en infinidad de implementaciones, ya que por sus características permite comunicarse de forma directa con el hardware, con lo cual podemos llevar a cabo tareas con dispositivos que de otro modo sería imposible, como por ejemplo la creación de códigos de arranque, la ingeniería inversa, la manipulación y programación de hardware y mucho más.

    Esto significa que aún en la actualidad, un programador puede generar ingresos importantes gracias a los lenguajes compiladores, y es uno de los campos de la informática menos explorados, por lo cual son pocos los profesionales con los que podemos competir aquí.

    Si queremos conocer más acerca de las implementaciones modernas del lenguaje ensamblador, más adelante en este mismo artículo tenemos mucha más información al respecto.

    Que es el lenguaje ensamblador

    Básicamente, un lenguaje ensamblador es un lenguaje de programación de bajo nivel utilizado para manipular las instrucciones internas de un dispositivo. Este lenguaje se puede utilizar de esta manera debido fundamentalmente a que siempre el lenguaje ensamblador ofrece una correspondencia uno a uno entre si y las instrucciones de código de máquina brutas del dispositivo que se está programando. Esto significa que cada línea de código del lenguaje ensamblador equivale perfectamente a una instrucción del dispositivo que se está programando, por lo cual no debe ni interpretarse ni compilarse para que el hardware “entienda”.

    En una explicación un poco más técnica, el lenguaje ensamblador, “Assembly” o “ASM” por su nombre en inglés, es una serie de mnemónicos que están diseñados para representar instrucciones básicas para microprocesadores, microcontroladores y otros circuitos integrados programables, como los presentes en toda computadora con sus procesadores, los televisores, dispositivos de audio, smartphones y mucho otro hardware.

    Estos mnemónicos son básicamente una representación simbólica de los códigos de máquina binarios, constantes y demás elementos de programación que necesitamos para llevar a cabo la tarea de hacer que un determinado procesador o microprocesador realice una determinada acción, dependiendo de su arquitectura y tipo.

    En este sentido, cabe destacar que para cada arquitectura de procesador es necesario un lenguaje ensamblador específico, que en términos generales siempre es definido por el fabricante del hardware. Esto es así debido a que los desarrollos de dispositivos se basan en un conjunto de instrucciones, registros, posiciones de memoria y otras características propias de un determinado lenguaje de ensamblador, y si intentamos programarlo de otra forma, será imposible.

    Esto significa que un lenguaje ensamblador es específico de una arquitectura de computadora en particular, al contrario de los modernos lenguajes de programación de alto nivel de la actualidad, que los podemos usar independientemente de la arquitectura en la que fue desarrollado el dispositivo, como lo explicamos más abajo.

    Características del lenguaje ensamblador

    Así como los seres humanos necesitamos de un lenguaje para poder comunicarnos, el hardware también requiere de una manera que nos permita “hablar” con sus procesadores y hacerlos llevar a cabo lo que pretendemos. Como el hardware es incapaz de entender lo que le proponemos, ya que sólo usa una combinación de unos y ceros, llamado lenguaje de máquina, es necesario tener un lenguaje que oficie de intermediario. Esta es la función básica de un lenguaje ensamblador.

    Sin embargo, la tarea no es tan sencilla, ya que existen muchos tipos de hardware, con procesadores y microprocesadores diseñados en torno a arquitecturas muy distintas entre sí, lo que le otorga a la tarea un grado de dificultad bastante alto. Pero los lenguajes ensambladores comparten cierto tipo de características, las cuales vamos a citar a partir de este punto.

    Como mencionamos más arriba en este artículo, una de las principales características del lenguaje ensamblador es que no permite portarse a otras arquitecturas. Esto significa que un código que haya sido escrito para un determinado microprocesador o procesador no servirá para otro modelo o fabricante, salvo que llevemos a cabo un rediseño muy importante. En este sentido, las arquitecturas de procesador más conocidas y usadas son las Intel x86 e Intel x64, las arquitecturas de AMD y la arquitectura ARM, utilizada esta última en smartphones, tablet y computadoras portátiles más modernas.

    El hecho de que cada lenguaje de ensamblado sea específico para una arquitectura determinada impide que se puedan crear desarrollos verdaderamente multiplataforma como los que podemos desarrollar en los lenguajes de programación de alto nivel como JAVA o C.

    Otra característica sobresaliente de las apps desarrolladas directamente en un lenguaje ensamblador, es que son mucho más eficientes en términos de recursos del sistema, y mucho más rápidos también. Un programa desarrollado en lenguaje ensamblador puede ser bastante más eficiente que un programa desarrollado en un lenguaje de alto nivel, sin embargo, gracias a los compiladores de los lenguajes de programación de alto nivel actuales, esta característica es cada vez menos requerida, ya que se mediante estos lenguajes se pueden crear también programas muy eficientes en términos de velocidad y estabilidad.

    También mediante el lenguaje ensamblador los desarrolladores pueden tener un control mucho más efectivo de los procesos a llevar a cabo por el procesador que se está programando, ya que este lenguaje, como mencionamos, ofrece la particularidad de poder comunicarse directamente con el hardware, una función que no se encuentra disponible en lenguajes de alto nivel, y que permite diseñar código muy específico.

    Cabe destacar que el código fuente resultante de este desarrollo en lenguaje ensamblador tiene la extensión “asm”, y a parir de este archivo se crea el código máquina, el cual suele te4ner una extensión de archivo “Hex”.

    Tipos de ensambladores

    En la actualidad existen múltiples tipos de lenguaje ensamblador, que si bien realizan la misma función final, varían de acuerdo al tipo de escenario en el que se lo utiliza.

    Ensamblador Cruzado: El primer tipo de ensamblador permite el soporte de medios físicos tales como periféricos de entrada y salida, y es utilizado principalmente en el desarrollo de programación para sistemas específicos.

    Ensamblador Residente: Este tipo de ensambladores permanecen en la memoria de la computadora, y solamente se cargan para permitir la ejecución del programa objeto producido. Este tipo de ensamblador es el más usado para la ingeniería de sistemas de control más pequeños.

    Macroensambladores: Este tipo específico de ensamblador permite el uso de macroinstrucciones, y son aplicaciones, muchas veces de gran tamaño, que tienen la particularidad de no permanecer en memoria una vez que se ha terminado de generar el código objeto.

    Microensambladores: Este tipo de ensambladores le proporciona al interprete instrucciones precisas de cómo debe llevar a cabo la CPU una determinada tarea.

    Ensambladores de una fase: Los ensambladores de una fase tienen la particularidad de leer una línea de programa fuente, traducirla directamente y producir una instrucción en lenguaje máquina por vez. Este tipo de ensambladores son sencillos de utilizar, y además brindan como beneficio ocupar poco espacio en memoria.

    Ensambladores de dos fases: Es el tipo de ensamblador más usado en la actualidad. Su nombre se debe a que todo el proceso de traducción y ejecución se lleva a cabo en dos etapas. En la primera de ellas el ensamblador analiza el código fuente y lo construyen en una tabla de símbolos. En la segunda etapa, se vuelve a analizar el código fuente del programa ya para traducirlo.

    Como es un programa en lenguaje ensamblador

    Básicamente, un programa realizado en lenguaje ensamblador estará formado por una secuencia de sentencias. Cada una de estas sentencias ocupa una sola línea y se puede observar de la siguiente manera:

    [etiqueta] [operación] [operando] [ comentarios]

    Los cuatro campos de la sentencia son opcionales. En el caso que no se completara cualquiera de ellos, se tendría una sentencia vacía.

    Instrucciones: Estas sentencias representan órdenes al procesador y tras el proceso de compilación, son capaces de generar código ejecutable.

    Directivas: Estas sentencias dirigen el proceso de compilación o construcción del programa ejecutable, pero no son capaces de generar código ejecutable. Usualmente son utilizadas para aumentar la legibilidad del código fuente.

    (Model) Segmento de datos: Contiene la dirección donde inicia la declaración de variables. Se escribe la variable.

    (Stack) Segmento de código: Contiene la dirección de inicio donde se encuentran las instrucciones del programa. Se escribe todo el código del programa a desarrollar.

    (Data) Segmento de pila: Contiene la dirección donde se encuentra la pila.

    (Code) Segmento Extra: Contiene la dirección donde podemos almacenar datos extras.

    Ejemplos de lenguaje ensamblador

    El siguiente es un ejemplo de programa desarrollado en lenguaje ensamblador para la arquitectura de procesador x86.

    .model small

    .stack

    .data

    Cadena1 DB 'Hola Mundo.$'

    .code

    programa:

    mov ax, @data

    mov ds, ax

    mov dx, offset Cadena1

    mov ah, 9

    int 21h

    int 20h

    end programa

    Aplicaciones del ensamblador

    En los inicios de la informática, y por consiguiente de la programación, las aplicaciones eran desarrolladas en forma total o parcial en alguno de los lenguajes ensambladores. Esto era así ya que los recursos existentes para procesar información eran más bien escasos, y el lenguaje ensamblador era una solución más que viable para conseguir una aplicación eficiente que funcionara bien con la poca memoria y potencia de procesador con que se contaba en las computadoras de aquella época.

    Con los años, la capacidad de las memorias y los procesadores se multiplicó varias veces en términos de potencia y velocidad, lo que traje como consecuencia que los programas fueran cada vez más complejos aprovechando las virtudes de estos nuevos procesadores y memorias.

    En este punto, los lenguajes ensambladores, tan necesarios en otras épocas, fueron reemplazados en las tareas de programación por lenguajes de alto nivel como por ejemplo C, FORTRAN y COBOL, o lenguajes orientados a objetos, los que son capaces de lograr millones de líneas de código y crear código tan eficiente como el logrado con el lenguaje ensamblador.

    En este sentido, los lenguajes de programación orientados a objetos han permitido crear desarrollos de software enormes, lo que sería imposible de llevar a cabo mediante un lenguaje ensamblador, debido fundamentalmente a que son millones de líneas de código, y recordando que cada orden del lenguaje ensamblador equivale a una instrucción en un procesador, podían tardarse años en escribir softwares complejos y enormes como los actuales.

    Sin embargo, el lenguaje ensamblador todavía se utiliza en la actualidad en los desarrollos modernos para conseguir tener acceso al hardware, pero también se utiliza para programar dispositivos pequeños, ya que es ideal, por el poco espacio que ocupan los programas desarrollados en lenguaje ensamblador, para este tipo de tareas. A continuación encontraremos algunos ejemplos de cómo se usa hoy en día el lenguaje ensamblador.

    Lenguaje ensamblador en consolas de videojuegos

    Una consola de videojuegos necesita que el software y el hardware que la controle se encuentren perfectamente optimizado para que puede ejecutarse de la manera más efectiva y rápida posible. Por este motivo los desarrolladores de este tipo de dispositivos utilizan el lenguaje ensamblador para escribir el código necesario que aproveche hasta el último bit del hardware existente.

    El uso del lenguaje ensamblador les permite a los diseñadores obtener acceso directo al hardware de las consolas y por lo tanto hacer los ajustes manuales pertinentes para obtener toda la potencia de los diferentes componentes de la consola. En este sentido los programadores de aplicaciones también hacen uso del lenguaje ensamblador para sus desarrollos en lugar de usar lenguajes de alto nivel más fáciles de implementar, ya que básicamente les permite tener altos valores de eficiencia, debido a que el software interactúa directamente con el hardware.

    Lenguaje ensamblador en sistemas embebidos

    Los sistemas embebidos son aquellos programas que controlan las funciones de diversos dispositivos específicos tales como tarjetas de video, discos duros, sistemas de seguridad, módems, teléfonos celulares, sistemas de control de aire acondicionado, instrumentos para la adquisición de datos y muchos otros. Este tipo de dispositivos se programan mediante un lenguaje ensamblador debido a que estos son pequeños y se pueden almacenar de manera sencilla en la ROM de estos aparatos, y al cumplir con una única función, su desarrollo no es tan complicado.

    En la actualidad, la programación de los microcontroladores de sistemas embebidos es el uso más corriente de un lenguaje ensamblador. Cualquiera de las funciones que nos ofrezca un dispositivo, sea una heladera o la computadora de un automóvil es controlada por un procesador de este tipo, el cual debe ser programado con anterioridad para llevar a cabo esa función específica.

    Lenguaje ensamblador en controladores de dispositivos de hardware

    Un controlador de dispositivos básicamente es un programa informático que le permite al sistema operativo interaccionar de manera directa con un periférico, con el objetivo que el usuario lo pueda usar sin tener que conocer su funcionamiento, tan sólo pulsar sobre un botón para obtener un resultado. Sin un controlador de dispositivos sería imposible utilizar un hardware.

    Debido a esta condición, la programación de un controlador de dispositivo se lleva a cabo mediante un lenguaje de ensamblador, ya que se puede acceder directamente al hardware para que este haga lo que el diseñador quiere, y presentarlo al usuario de la manera más sencilla y clara posible.

    Graciela Marker

    Periodista independiente con más de 20 años de experiencia en medios gráficos, audiovisuales y digitales. Formada académicamente en periodismo digital y comunicación multimedia, ámbito en el que se desenvuelve hace dos décadas. Especializada en ámbitos tales como la informática y la logística empresarial, entre otros.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Subir

    Usamos cookies para darte una mejor experiencia de navegación. Si continuas navegando, aceptas su uso. Más Información sobre nuestras Cookies