Definición
En informática, una instrucción es una operación única que ejecuta un procesador, definida por el conjunto de instrucciones (ISA) de ese procesador. De forma más general, una "instrucción" puede entenderse como cualquier representación de un elemento ejecutable de un programa de ordenador.
Componentes y significado
Tradicionalmente, una instrucción incluye:
- Opcode: el código de operación que especifica qué hacer (por ejemplo, sumar, cargar, almacenar, saltar). Véase opcode.
- Operandos: cero o más especificadores que indican los datos sobre los que actúa la operación (registros, direcciones de memoria o literals). En el texto original se mencionan especificadores de operandos.
- Modos de direccionamiento: mecanismos que determinan cómo se interpreta cada especificador de operando, por ejemplo inmediato, directo, indirecto, indexado o relativo (modos de direccionamiento).
Los especificadores pueden estar en campos fijos de la instrucción o codificarse mediante bits que indican el modo o la longitud de los operandos.
Tamaños y formatos de instrucción
El tamaño o longitud de una instrucción varía mucho entre arquitecturas. Puede ser tan pequeño como 4 bits en algunos microcontroladores y llegar a múltiples bytes en diseños VLIW. La mayoría de procesadores modernos usados en ordenadores personales, mainframes y superordenadores manejan instrucciones de entre 16 y 64 bits.
Existen dos enfoques habituales:
- Longitud fija: cada instrucción ocupa el mismo número de bits (común en arquitecturas RISC, como las de conjunto de instrucciones reducidas), lo que simplifica el decodificador y el pipeline y suele corresponder al tamaño de palabra.
- Longitud variable: las instrucciones tienen tamaños distintos según la operación (común en arquitecturas CISC, por ejemplo muchos diseños x86). Permite una codificación más densa pero complica la decodificación.
En las arquitecturas VLIW, se agrupan múltiples operaciones y operandos en una sola instrucción larga que el hardware ejecuta en paralelo. También hay arquitecturas que usan microcódigo para implementar instrucciones complejas dividiéndolas en secuencias más simples.
Tipos de instrucciones
Las instrucciones pueden clasificarse según su función. Algunos tipos frecuentes son:
- Transferencia de datos: cargar y almacenar entre memoria y registros.
- Aritméticas y de punto flotante: suma, resta, multiplicación, división, operaciones sobre punto flotante.
- Lógicas: AND, OR, XOR, desplazamientos y rotaciones.
- Control de flujo: saltos condicionales e incondicionales, llamadas a subrutinas y retornos.
- Entrada/Salida: instrucciones para acceder a dispositivos periféricos.
- Privilegiadas o de sistema: operaciones que solo pueden ejecutar el sistema operativo (cambio de modo, gestión de memoria, control de interrupciones).
- Stack-based: arquitecturas que usan la pila como estructura principal de operandos (p. ej. algunas máquinas virtuales).
Representación y niveles de lenguaje
Las instrucciones raramente se escriben directamente en forma de código máquina. Los programadores utilizan un lenguaje ensamblador con mnemónicos legibles (por ejemplo ADD, MOV) que representan opcodes y operandos. Más comúnmente, las instrucciones se generan por los compiladores que traducen código de alto nivel a secuencias de instrucciones del ISA.
Además:
- El ensamblador convierte el código ensamblador en código máquina (binario) y produce ficheros objeto.
- Los desensambladores hacen el proceso inverso para analizar binarios.
- En algunos procesadores, una instrucción compleja se implementa mediante microinstrucciones dentro del microcódigo.
Ciclo de instrucción y ejecución
El procesamiento de una instrucción en el procesador suele implicar varias fases básicas: fetch (búsqueda), decode (decodificación), execute (ejecución), acceso a memoria y write-back (escritura del resultado). En arquitecturas modernas con pipeline, estas fases se superponen para mejorar el rendimiento. Esto introduce conceptos como dependencia de datos, riesgos (hazards) y control (branch hazards) que deben gestionarse con técnicas como reordenamiento, predicción de saltos o ejecución fuera de orden.
Ejemplos de formatos
Algunos ISAs definen formatos concretos por tipo de instrucción. Por ejemplo, en arquitecturas RISC como MIPS es común distinguir:
- R-type: instrucciones que operan entre registros (campos para opcode, registros fuente y destino, y campo de función).
- I-type: instrucciones con un operando inmediato (inmediatos de 16 bits en MIPS).
- J-type: instrucciones de salto con un campo amplio para la dirección.
En cambio, ISAs como x86 usan longitudes variables y campos menos regulares, lo que permite codificaciones más compactas pero más complejas de decodificar.
Consideraciones prácticas
- Alineación: muchas arquitecturas requieren que las instrucciones estén alineadas en memoria según su tamaño de palabra; la alineación afecta el rendimiento y la corrección.
- Endianness: el orden de bytes en memoria puede influir en cómo se interpretan los bits del código máquina.
- Compatibilidad y extensiones: los conjuntos de instrucciones evolucionan (nuevas instrucciones SIMD, instrucciones para criptografía, etc.), y los compiladores y ensambladores se actualizan para aprovecharlas.
- Seguridad: instrucciones privilegiadas y la gestión de excepciones son críticas para la protección del sistema; errores en la decodificación o ejecución pueden dar lugar a vulnerabilidades.
Resumen
Una instrucción es la unidad mínima ejecutable que describe una operación para el procesador. Incluye típicamente un opcode y especificadores de operandos, y su longitud y formato dependen del diseño del conjunto de instrucciones. Se representan en código máquina, se escriben en ensamblador y suelen ser generadas por compiladores. En arquitecturas avanzadas como VLIW o aquellas que usan microcódigo, una única instrucción puede especificar múltiples operaciones o descomponerse en microinstrucciones.