Fundamentos del Lenguaje Ensamblador: Arquitectura y Programación x86
Enviado por Programa Chuletas y clasificado en Informática y Telecomunicaciones
Escrito el en
español con un tamaño de 8,02 KB
Introducción a la Programación de Bajo Nivel
Para comprender en profundidad el funcionamiento de un sistema informático, es fundamental que los programadores manejen conceptos clave como la memoria virtual, las interrupciones, la interacción con el hardware (HW) y la memoria caché. Los lenguajes de bajo nivel, como el lenguaje ensamblador, ofrecen un control directo sobre estos elementos. La claridad y la concisión son cruciales al trabajar con ellos.
Es importante destacar que cada arquitectura de procesador tiene su propio lenguaje ensamblador. En este documento, nos centraremos en la popular arquitectura x86 de Intel.
El Lenguaje Ensamblador
Los lenguajes ensambladores son la representación simbólica del código máquina binario y siguen la arquitectura de Von Neumann. Su principio fundamental es asignar un mnemotécnico (una palabra fácil de recordar) a cada instrucción de máquina. Esto mejora drásticamente la legibilidad en comparación con una secuencia de ceros y unos.
Por ejemplo, para la operación x = y;, las instrucciones varían según la arquitectura:
- Intel 80x86:
mov ax, xseguido demov y, ax. - Motorola 68000:
move x, D0seguido demove D0, y.
La estructura general de una línea de código en ensamblador es:
ETIQUETA INSTRUCCIÓN OPERANDOS ;COMENTARIO
Ventajas e Inconvenientes
Ventajas
- Mayor legibilidad: Es mucho más comprensible que el código máquina.
- Flexibilidad y control total: Permite acceder a todas las capacidades del hardware. Esto lo mantiene vigente en áreas críticas como el desarrollo de sistemas empotrados, núcleos de sistemas operativos y software para dispositivos móviles.
Inconvenientes
- Complejidad: Es un lenguaje tedioso y difícil de aprender y utilizar.
- Nula portabilidad: El código escrito para una arquitectura no funciona en otra.
- Baja granularidad: Se necesitan muchas instrucciones para realizar tareas sencillas.
- Poca redundancia: El ensamblador realiza muy pocas comprobaciones para asegurar que el programador está haciendo las cosas correctamente, lo que facilita la aparición de errores.
Características del Lenguaje Ensamblador
Las características de un lenguaje ensamblador están intrínsecamente ligadas a la arquitectura del procesador para el que fue diseñado. A continuación, se detallan los aspectos más relevantes.
Conjunto de Instrucciones: CISC vs. RISC
Las arquitecturas de procesadores se clasifican principalmente en dos tipos:
- CISC (Complex Instruction Set Computer): Poseen un conjunto de instrucciones amplio y complejo, donde una sola instrucción puede realizar múltiples operaciones de bajo nivel (como una lectura de memoria, una operación aritmética y una escritura en memoria). Un ejemplo en x86 sería:
mov ax, [1234h + BX + 2*DI]. - RISC (Reduced Instruction Set Computer): Cuentan con un conjunto de instrucciones más pequeño y simple. Cada instrucción realiza una única operación. La instrucción CISC anterior requeriría al menos cuatro instrucciones diferentes en una arquitectura RISC.
Número de Operandos por Instrucción
Las instrucciones pueden clasificarse según el número de operandos que manejan:
- 3 operandos: Dos operandos fuente y un operando destino donde se almacena el resultado.
- 2 operandos: Uno de los operandos fuente es también el destino, por lo que su valor original se sobrescribe.
- 1 operando: Operan sobre un acumulador o una pila (stack).
- 4 operandos: Es un caso más teórico que práctico.
Modos de Direccionamiento
Los modos de direccionamiento definen cómo la CPU localiza los operandos necesarios para ejecutar una instrucción.
Direccionamiento para el Código
- Absoluto: La instrucción contiene la dirección de memoria exacta a la que se debe saltar.
- Relativo al programa: Se especifica un desplazamiento que se suma al contador de programa (PC o IP) para obtener la nueva dirección.
- Indirecto a registro: La dirección de salto está almacenada en un registro.
Direccionamiento para los Datos
- Inmediato: El propio dato (un valor constante) forma parte de la instrucción.
- Directo: La instrucción contiene la dirección de memoria absoluta del dato, o el operando es un registro que contiene el dato.
- Indirecto: El dato está en una posición de memoria que debe calcularse. Puede ser mediante un registro, relativo a un registro base (registro + constante) o indexado (absoluto o relativo a una base).
Ortogonalidad
La ortogonalidad indica si todos los modos de direccionamiento están disponibles para todos los tipos de instrucciones y todos los registros. Las arquitecturas RISC tienden a ser más ortogonales, lo que simplifica el diseño de compiladores.
Ejemplo de Lenguaje Ensamblador: Intel 80x86
La familia de procesadores Intel 80x86, que comenzó su andadura en 1978-79, es un claro ejemplo de arquitectura CISC. Una de sus características más importantes es que mantiene la compatibilidad hacia atrás con sus versiones anteriores.
Arquitectura
La arquitectura 8086 ha evolucionado de 16 a 32 y 64 bits, permitiendo realizar operaciones aritméticas y lógicas complejas. Sus componentes principales son los registros.
Registros Principales
Registros de Propósito General
Son registros de 16 bits (AX, BX, CX, DX) que pueden dividirse en dos registros de 8 bits (parte alta 'H' y parte baja 'L', por ejemplo, AH y AL). A partir del procesador 80386, se introdujeron las versiones extendidas de 32 bits (EAX, EBX, etc.).
Registros de Segmento
Permiten gestionar la memoria mediante un sistema de segmentos. Un registro almacena la dirección de inicio del segmento y otro (un puntero o índice) almacena el desplazamiento dentro de ese segmento.
Registros Base y Punteros
- Registros de Índice: SI (Source Index) y DI (Destination Index), usados para operaciones con cadenas de datos.
- Punteros de Pila: SP (Stack Pointer).
- Puntero de Instrucción: IP (Instruction Pointer), que apunta a la siguiente instrucción a ejecutar.
Instrucciones Básicas
mov destino, origen: Copia el valor del origen en el destino.add ax, bx: Suma el contenido de AX y BX y guarda el resultado en AX.and ax, bx: Realiza una operación AND a nivel de bits entre AX y BX.cmp ax, bx: Compara los valores de AX y BX (resta sin guardar el resultado) y actualiza los flags de estado.
Modos de Direccionamiento en Intel 80x86
- Inmediato:
mov ah, 03h - Directo Absoluto:
mov ax, [0017h] - Indirecto a Registro:
mov ax, [bx]
Conclusiones
Aunque el uso del lenguaje ensamblador ha disminuido en la programación de aplicaciones generales, sigue siendo una herramienta indispensable en nichos específicos como los sistemas embebidos y la programación de hardware de bajo nivel. Su estudio y comprensión proporcionan una visión profunda del funcionamiento interno de un ordenador, un conocimiento de gran valor para cualquier profesional de la informática.