Introducción al Lenguaje Ensamblador x86
Conceptos, estructura, modos de direccionamiento, control de flujo, instrucciones y ejercicios prácticos en ensamblador x86.
⚙️ Introducción a la Arquitectura x86 y Lenguaje Ensamblador
¿Qué es el lenguaje ensamblador?
El lenguaje ensamblador es un lenguaje de bajo nivel, muy cercano al hardware. Utiliza mnemotécnicos (MOV, ADD, INT) para representar instrucciones que se traducen directamente a código de máquina y es específico de cada arquitectura (x86, ARM, etc.).
- Usa mnemotécnicos para instrucciones.
- Traducción directa a binario.
- Específico de cada arquitectura.
Evolución de la arquitectura x86
| Procesador | Año | Bits | Descripción |
|---|---|---|---|
| Intel 8086/8088 | 1978 | 16 | Primeros procesadores x86 |
| Intel 80386 | 1985 | 32 | Extensión a 32 bits (IA-32) |
| AMD64 | 2003 | 64 | AMD introduce x86-64, luego adoptado por Intel |
¿Por qué aprender ensamblador x86?
- Base de sistemas operativos (Windows, Linux)
- Usado en drivers, firmware y sistemas embebidos
- Permite entender el funcionamiento real de la CPU
🏗️ Estructura de un Programa en Ensamblador
Segmentos en Ensamblador
| Segmento | Función | Ejemplo |
|---|---|---|
| .DATA | Variables y constantes | msg DB 'Hola$' |
| .CODE | Instrucciones del programa | MOV AX, 5 |
| .STACK | Memoria temporal (pila) | .STACK 100h |
Modelos de memoria
- TINY: Todo en un solo segmento (programas pequeños)
- SMALL: Un segmento para código y otro para datos
- LARGE: Múltiples segmentos para código y datos
Ejemplo básico: Hola Mundo
.MODEL SMALL
.STACK 100h
.DATA
msg DB 'Hola Mundo$'
.CODE
MOV AX, @DATA
MOV DS, AX ; Inicializa segmento de datos
LEA DX, msg ; Carga dirección del mensaje
MOV AH, 09h ; Función para imprimir
INT 21h ; Llama al sistema operativo
MOV AH, 4Ch ; Terminar programa
INT 21h📍 Modos de Direccionamiento
| Modo | Ejemplo | Explicación |
|---|---|---|
| Inmediato | MOV AX, 10 | El dato está en la instrucción |
| Directo | MOV AX, [1000h] | La dirección del dato está en la instrucción |
| Por registro | MOV AX, BX | Usa un registro del CPU |
| Indexado | MOV AX, [BX+SI] | Combina registros y desplazamientos |
Los modos de direccionamiento determinan cómo se accede a la memoria y afectan el rendimiento del programa.
🔄 Estructuras de Control de Flujo
Secuenciales
Las instrucciones se ejecutan en orden, una tras otra.
Condicionales
Permiten tomar decisiones:
IF-ELSE
CMP AX, BX ; Compara AX y BX
JE iguales ; Salta si son iguales
; Código si no son iguales
JMP fin
iguales:
; Código si son iguales
fin:SWITCH-CASE
Se simula con saltos condicionales (JMP, JE, JNE).
Iterativas (Bucles)
FOR
MOV CX, 10 ; Repetir 10 veces
ciclo:
; Código del bucle
LOOP cicloWHILE
inicio_while:
CMP AX, BX
JNE fin_while
; Código del bucle
JMP inicio_while
fin_while:🛠️ Instrucciones Básicas en Ensamblador
| Instrucción | Ejemplo | Descripción |
|---|---|---|
| MOV | MOV AX, BX | Copia el valor de BX a AX |
| ADD | ADD AX, 5 | Suma 5 a AX |
| SUB | SUB AX, BX | Resta BX de AX |
| INT | INT 21h | Llama a una función del sistema |
| CMP | CMP AX, BX | Compara AX y BX (para condicionales) |
| JMP | JMP etiqueta | Salta a una etiqueta |
Interrupciones importantes (INT 21h)
- AH = 09h: Imprimir cadena
- AH = 01h: Leer un carácter
- AH = 4Ch: Terminar programa
📝 Ejercicios Prácticos
1. Suma de dos números
section .text
global _start
_start:
mov al, 4 ; primer número
add al, 9 ; segundo número (4+9=13)
mov ah, 0 ; limpiar AH antes de dividir
mov bl, 10
div bl ; divide AX por BL: AL = cociente(decena), AH = resto(unidad)
; Convertir cociente (decena) y resto (unidad) a ASCII
add al, '0'
mov [decena], al
add ah, '0'
mov [unidad], ah
; Mostrar decena si no es cero
cmp byte [decena], '0'
je mostrar_unidad
mov eax, 4 ; syscall sys_write
mov ebx, 1 ; stdout
mov ecx, decena
mov edx, 1
int 0x80
mostrar_unidad:
mov eax, 4
mov ebx, 1
mov ecx, unidad
mov edx, 1
int 0x80
; Salir
mov eax, 1
mov ebx, 0
int 0x80
section .bss
decena resb 1
unidad resb 1
2. Contar dígitos de un número
section .data
num db '123456789$', 0
section .bss
decena resb 1
unidad resb 1
section .text
global _start
_start:
mov esi, num ; puntero a la cadena
mov cx, 0 ; contador
contar:
mov al, [esi]
cmp al, '$'
je convertir
inc cx
inc esi
jmp contar
convertir:
mov ax, cx
mov bl, 10
xor dx, dx
div bl ; AX / 10, AL = cociente(decena), AH= resto(unidad)
add al, '0' ; convertir decena a ASCII
mov [decena], al
add ah, '0' ; convertir unidad a ASCII
mov [unidad], ah
; Mostrar decena si no es '0'
cmp byte [decena], '0'
je mostrar_unidad
mov eax, 4 ; sys_write
mov ebx, 1 ; stdout
mov ecx, decena
mov edx, 1
int 0x80
mostrar_unidad:
mov eax, 4 ; sys_write
mov ebx, 1
mov ecx, unidad
mov edx, 1
int 0x80
; Salir
mov eax, 1 ; sys_exit
xor ebx, ebx
int 0x80Simulador interactivo de código ensamblador x86
Puedes escribir y ejecutar código ensamblador x86 directamente en el simulador de arriba. Es ideal para probar ejemplos como los de esta guía.
🏁 Conclusión
- El ensamblador x86 es fundamental para entender cómo funcionan las computadoras.
- Se usa en sistemas operativos, drivers y aplicaciones de bajo nivel.
- Aunque es complejo, dominarlo permite optimizar código y entender la arquitectura de la CPU.
Arquitectura del Microprocesador
Exploración de las arquitecturas Von Neumann y Harvard, junto con la conexión del microprocesador y diagramas de bloques.
Constantes, Operadores y Estructuras en Ensamblador x86 (Sintaxis NASM/Linux)
Constantes, operadores, tipos de datos, instrucciones, E/S, procedimientos y macros en ensamblador x86 adaptados a NASM y syscalls Linux.