Instrucciones y registros en NASM (16 bits)
En el desarrollo de sistemas en ensamblador NASM en modo real (16 bits), se utilizan distintos registros, instrucciones y modos de operación fundamentales para controlar el flujo del programa y manipular datos a bajo nivel.
📦 Registros en modo real
Los registros son espacios pequeños dentro del procesador donde se almacenan datos temporalmente. En modo real (como en el i386 en 16 bits), se agrupan por función:
🔹 Registros de propósito general
- AX: acumulador, se usa en operaciones aritméticas y de E/S.
- BX: base, útil para direccionamiento.
- CX: contador, común en bucles y operaciones repetitivas.
- DX: datos, usado también en multiplicación/división o E/S.
Cada uno tiene versiones de 8 bits (por ejemplo, AH/AL para AX, BH/BL para BX).
🔹 Registros de segmento
- CS: segmento de código (donde está el programa).
- DS: segmento de datos.
- SS: segmento de pila.
- ES: segmento extra, se puede usar para transferencias de datos.
🔹 Registros de índice y punteros
- SI/DI: fuente y destino en operaciones con cadenas.
- SP/BP: puntero de pila y base de pila.
🔹 Registro de instrucción
- IP: puntero de instrucción, señala la siguiente instrucción a ejecutar.
⚙️ Instrucciones de control de flujo
Estas instrucciones determinan cómo avanza el programa.
- JMP: salto incondicional a otra dirección.
- CALL: llama a una subrutina (guarda la dirección de retorno).
- RET: vuelve de una subrutina al punto donde fue llamada.
🔍 Instrucciones de comparación y saltos condicionales
Se usan para tomar decisiones dentro del programa.
- CMP: compara dos operandos y actualiza los flags, sin modificar los operandos.
- JE / JZ: salta si son iguales (zero flag activado).
- JNE / JNZ: salta si no son iguales.
- JA, JB, JG, JL, etc.: saltos para comparaciones mayores o menores.
🧠 Modo real
En NASM de 16 bits, se trabaja en modo real, lo que significa:
- El procesador puede acceder a 1 MB de memoria.
- La dirección física se calcula con:
segmento * 16 + offset
. - No hay protección de memoria ni multitarea.
- Todo el código corre con acceso total al hardware.
Este modo es ideal para sistemas operativos simples, como este proyecto, donde se quiere tener control total sobre el comportamiento del sistema.
Interrupciones y funciones de interrupción
Interrupción:
Es una señal que interrumpe temporalmente la ejecución normal de un programa para atender eventos urgentes o realizar servicios específicos del sistema. Cuando se produce una interrupción, el procesador detiene su trabajo actual, guarda el estado y salta a una rutina especial para manejar esa interrupción.
Función de interrupción (Manejador de interrupción):
Es la rutina o función que se ejecuta cuando ocurre una interrupción. Esta función se encarga de procesar el evento que causó la interrupción, como leer una tecla, atender un dispositivo o gestionar una operación de sistema. Al finalizar, devuelve el control al programa interrumpido.
Tabla de interrupciones más típicas
Interrupción | Función principal | Ejemplo de uso |
---|---|---|
INT 0x10 | Servicios de video y pantalla | Cambiar el modo gráfico o imprimir texto en pantalla. |
INT 0x13 | Acceso a disco | Leer o escribir sectores en disco duro o disquete. |
INT 0x16 | Entrada desde teclado | Leer la tecla pulsada por el usuario. |
INT 0x21 | Servicios del sistema DOS | Abrir, leer o escribir archivos, mostrar texto. |
INT 0x15 | Servicios del sistema BIOS | Obtener información del sistema o controlar dispositivos. |
INT 0x1A | Servicios de reloj del sistema | Leer el reloj de tiempo real o temporizadores. |
INT 0x33 | Control del ratón | Obtener posición y estado de los botones del ratón. |
INT 0x31 | Servicios de DOS extendido | Acceso avanzado a memoria o funcionalidades extendidas. |
La pila y las instrucciones PUSH y POP
La pila es una estructura de datos que funciona con el principio LIFO (Last In, First Out), es decir, el último dato que se guarda es el primero que se recupera. En programación de bajo nivel y ensamblador, la pila es fundamental para almacenar valores temporales, direcciones de retorno y para manejar llamadas a funciones.
- PUSH: Esta instrucción inserta (empuja) un valor en la cima de la pila, decrementando el puntero de la pila (
SP
oESP
según la arquitectura) y guardando el dato en esa posición. - POP: Esta instrucción extrae (saca) el valor de la cima de la pila, incrementando el puntero de la pila y recuperando el dato para usarlo en registros o memoria.
La pila permite, entre otras cosas, guardar el estado antes de llamar a una función (como los registros y la dirección de retorno) y restaurarlo después, facilitando la gestión del flujo del programa y la recursión.