2. Programación Básica
https://www.jdoodle.com/compile-assembler-nasm-online
Unidad 2: Programación Estructurada y Avanzada en Ensamblador
Plataforma académica interactiva con los 16 temas completamente desarrollados. Códigos listos para JDoodle (NASM 32-bit Linux, int 0x80).
Bloque 1: Entorno, Entrada de Datos y Bifurcaciones
2.1 Ensamblador (y ligador) a utilizar
En entornos modernos de 64 bits, la forma nativa de compilar bajo nivel educativo es mediante la sintaxis **NASM (Netwide Assembler)**. El ensamblador genera un archivo objeto binario formateado para Linux (.o), y el ligador de GNU (ld) enlaza los segmentos de memoria para definir el punto de entrada e instrucciones ejecutables reales.
2.2 Ciclos numéricos
La CPU utiliza estructuras cíclicas basadas en registros contadores fijos. La instrucción nativa LOOP resta automáticamente 1 de ECX/CX y comprueba si el resultado es cero; si no lo es, desvía el flujo del programa hacia la etiqueta designada en el segmento de código.
2.3 Captura básica de cadenas
La recolección de texto proveniente de la terminal o teclado se efectúa cargando el código de servicio 3 (sys_read) en el registro de control EAX, definiendo en EBX el descriptor de entrada estándar (0 para STDIN) y apuntando ECX hacia un búfer dinámico en memoria.
2.4 Comparación y prueba
La instrucción CMP resta internamente el operando derecho del izquierdo sin guardar el resultado, alterando las banderas de estado (ZF, CF, SF) en el registro EFLAGS. Por su parte, TEST realiza una operación lógica AND bit por bit, útil para comprobar si ciertos bits específicos están encendidos.
2.5 Saltos
La CPU cambia el orden lineal de ejecución de instrucciones modificando el puntero EIP. Los saltos se dividen en **Incondicionales** (JMP, se ejecutan sin importar nada) y **Condicionales** (JE, JNE, JG, JL), los cuales se disparan solo si las banderas del procesador cumplen una condición matemática previa.
section .data
msg_match db "Los numeros coinciden", 10
len_match equ $ - msg_match
section .text
global _start
_start:
mov eax, 50 ; Registro A
mov ebx, 50 ; Registro B
cmp eax, ebx ; 2.4 Comparación aritmética
je saltar_a_meta ; 2.5 Salto Condicional si son iguales (ZF=1)
jmp salir_programa ; 2.5 Salto Incondicional de escape
saltar_a_meta:
mov eax, 4 ; Syscall sys_write
mov ebx, 1 ; Descriptor stdout (Pantalla)
mov ecx, msg_match ; Dirección del mensaje
mov edx, len_match ; Longitud
int 0x80 ; Interrupción de Kernel
salir_programa:
mov eax, 1 ; Syscall sys_exit
xor ebx, ebx ; Código de retorno 0
int 0x80
Bloque 2: Repeticiones Controladas y Operaciones Aritméticas
2.6 Ciclos condicionales
A diferencia de los ciclos numéricos puros, los ciclos condicionales dependen del cumplimiento de un estado dinámico en las banderas del procesador. Se estructuran combinando instrucciones de salto relacionales como JNZ (Jump if Not Zero) o JZ al final del cuerpo de un bucle de procesamiento de datos.
2.7 Incremento y decremento
Las instrucciones INC y DEC modifican el operando sumando o restando una unidad aritmética de forma exacta. Son significativamente más rápidas que usar instrucciones generales como ADD o SUB debido a que requieren microinstrucciones de menor tamaño dentro de la ALU.
2.8 Captura de cadenas con formato
La captura estructurada impone restricciones severas al flujo de caracteres. Se define un tamaño de almacenamiento inamovible en la sección de memoria de variables no inicializadas (.bss) utilizando la directiva resb, garantizando que el usuario no pueda desbordar la memoria adyacente.
2.9 Instrucciones aritméticas
El repertorio matemático básico del procesador incluye ADD (suma), SUB (resta), MUL (multiplicación sin signo) y DIV (división). En las multiplicaciones de 32 bits, el multiplicando se aloja obligatoriamente en EAX, y el resultado extendido se almacena en la combinación de registros EDX:EAX.
section .text
global _start
_start:
mov ecx, 5 ; Inicializamos un contador manual en 5
mov eax, 2 ; Valor acumulador base
ciclo_aritmetico:
mov ebx, 3
mul ebx ; 2.9 Multiplicación: EAX = EAX * 3
inc eax ; 2.7 Incremento: EAX = EAX + 1
dec ecx ; 2.7 Decremento: ECX = ECX - 1
jnz ciclo_aritmetico ; 2.6 Ciclo Condicional: Repite mientras ECX != 0
mov eax, 1 ; Terminar programa (sys_exit)
xor ebx, ebx
int 0x80
Bloque 3: Gestión de Memoria, Conversión Decimal y Álgebra Booleana
2.10 Manipulación de la pila
La Pila (Stack) es un segmento de la memoria RAM regido bajo la política **LIFO** (Last In, First Out). La instrucción PUSH inserta datos en el tope reduciendo el puntero de pila ESP, mientras que POP extrae el dato y lo deposita en un registro, incrementando ESP de manera automática.
2.11 Obtención de cadena con representación decimal
Los registros almacenan valores binarios crudos. Para convertirlos en una cadena de texto decimal visible por humanos, el algoritmo exige dividir el número de forma matemática consecutiva entre 10. Cada residuo aislado (que oscila entre 0 y 9) se transforma en su carácter ASCII equivalente sumándole la constante 48 (o el carácter '0').
2.12 Instrucciones lógicas
Representan el álgebra de Boole implementada directo en compuertas de hardware. Las instrucciones fundamentales son: AND (máscaras de bits), OR (encendido de bits), XOR (limpieza veloz de registros al emparejar un operando consigo mismo) y NOT (inversión total del complemento a uno).
section .text
global _start
_start:
mov eax, 0xABCDE ; Carga de datos críticos
push eax ; 2.10 Resguarda el contenido en el Stack (Pila)
mov eax, 0xFF00 ; Variable de máscara
mov ebx, 0x0F0F ; Variable de datos
and eax, ebx ; 2.12 Operación Lógica AND bit por bit
xor ecx, ecx ; 2.12 XOR para limpiar a cero el registro ECX de forma óptima
pop eax ; 2.10 Restaura el valor original desde el Stack
mov eax, 1 ; sys_exit
int 0x80
Bloque 4: Operaciones de Bit Avanzadas, Hexadecimal y Archivos
2.13 Desplazamiento y rotación
Las instrucciones de desplazamiento mueven los bits a la izquierda (SHL, multiplica por 2) o a la derecha (SHR, divide entre 2), rellenando los espacios vacíos con ceros. Las rotaciones (ROL, ROR) reinsertan los bits expulsados por el extremo opuesto, impidiendo la pérdida de información.
2.14 Obtención de una cadena con la representación hexadecimal
Para codificar un número a texto base 16, se fragmenta el registro en bloques de 4 bits (nibbles) mediante máscaras lógicas. Si el bloque matemático resultante vale de 0 a 9, se le suma 48 ('0'); si su rango oscila entre 10 y 15, se le suma 55 para transformarlo con precisión en las letras de la 'A' a la 'F' en la tabla ASCII.
2.15 Captura y almacenamiento de datos numéricos
El teclado del sistema captura exclusivamente caracteres en formato de texto. El proceso inverso de almacenamiento numérico binario real requiere leer el buffer carácter por carácter, restar 48 para aislar el valor absoluto del dígito, y multiplicar la base acumulada de forma sucesiva por 10.
2.16 Operaciones básicas sobre archivos de disco
La administración física del sistema de archivos depende de las llamadas de servicios del Kernel de Linux. Involucra el uso estricto de identificadores funcionales: sys_open (EAX=5) para aperturas o creación configurando descriptores de permisos de lectura, sys_write (EAX=4) para almacenamiento secuencial y sys_close (EAX=6) para el cierre y salvaguarda final de datos.
section .text
global _start
_start:
mov eax, 12 ; Binario: 00001100 (12 decimal)
shl eax, 2 ; 2.13 Desplazamiento Izquierda: Multiplica por 4 -> Resulta 48
shr eax, 1 ; 2.13 Desplazamiento Derecha: Divide entre 2 -> Resulta 24
mov ebx, 0x0A ; Representación numérica base hexadecimal
rol ebx, 4 ; 2.13 Rotación de bits sin pérdida en el registro
mov eax, 1 ; Terminar ejecutable (sys_exit)
xor ebx, ebx
int 0x80
📊 Examen de Evaluación Integral de la Unidad 2
Valida de manera rigurosa tu conocimiento técnico en cada uno de los 16 temas desarrollados sobre la arquitectura del procesador.