Guía Hardware

¿Qué es un op_code?

Actualizado a: 16 de abril de 2024

Si aún no sabes qué es un op_code, aquí te lo explicaremos, y también aprenderás sobre algunos de estos códigos ocultos no documentados que son bastante misteriosos y que han dado mucho que hablar en algunos procesadores.

¿Qué es un op_code?

CPU

Un op_code o código de operación no es más que una instrucción que permite a la CPU realizar una operación cuando ésta la recibe y aplicar esta operación sobre los operandos, que son los datos.

Es decir, se puede entender como un código binario que puede ser interpretado por la CPU y que se usa para ejecutar tareas del hardware y hacer funcionar al software. Todos los op_codes o instrucciones se definirán en la ISA de la CPU, por lo que no serán entendibles por otra máquina o ISA diferente.

De esta forma, los programas creados por los programadores (una vez compilados y en formato binario) estarán compuestos por una serie de instrucciones y de datos que serán cargados en la memoria RAM y luego accedidos por la CPU para ser ejecutados de forma secuencial. Las instrucciones tendrán su op_code, que se interpretará para indicar a las unidades de ejecución qué deben hacer con os datos u operandos.

Por ejemplo, podrían indicar un desplazamiento de bits, una operación lógica, operaciones aritméticas, etc. Así es como funciona y creo que esto ya lo hemos explicado en otras ocasiones y queda bastante claro…

¿Cómo funciona un OP_CODE?

microarquitectura de cpu

Para que la CPU pueda recibir y procesar la información necesaria para ejecutar los programas, se necesitan estas órdenes o instrucciones básicas que estarám en formato binario para que puedan ser entendidas. No obstnate, durante la programación, para mayor abstracción y facilidad para el programador, se puede emplear un lenguaje de alto nivel o lenguaje ensamblador si se desea trabajar a más bajo nivel. En el lenguaje ensamblador, estas instrucciones estarán representadas como mnemónicos, para que sean más sencillas de recordar, y no en formato binario como el código máquina.

No voy a entrar en detalles de arquitecturas RISC-like y de micro-ops, y demás, ya que sería otro tema a tratar en un artícuo.

Una vez el programador termina de escribir el código fuente de su programa, puede pasar éste a un ejecutable binario que pueda entender la CPU mediante un compilador. Esto generará un archivo (o varios) ejecutables con los datos (variables, constantes,…) y las instrucciones en binario. Y cuando se ejecute esta app sobre el sistema operativo, la CPU se encargará de procesarlo.

Ahora bien, cuando un programa o proceso se carga en la memoria RAM por el planificiador del sistema operativo, en él no van más que las instrucciones y los operandos necesarios para su ejecución, pero antes deben pasar por la unidad de control, donde mediante el microcódigo serán interpretados estos op_codes y transformados en señales de control para indicarle a las unidades de ejecución dónde están los operandos y qué tienen que hacer con ellos para obtener el resultado querido.

Mediante un decodificador, la CPU podrá obtener eas señales de control a partir de las instrucciones recibidas y así es como funciona.

Cuando se hace un voltaje de la memoria, estos datos e instrucciones se pueden ver en formato hexadecimal también, y se pueden analizar con programas específicos. También se puede hacer para analizar programas mediante el desensamblado.

Tipos de op_codes

ALU

Existen varios tipos de op_codes que podemos englobar según su función. Por ejemplo, podemos encontrar los siguientes:

  • De transferencia de datos: este tipo de instrucciones sirven, como su propio nombre indica, para transferir datos desde una localización origen hasta otra destino. Generalmente, este tipo de códigos pueden buscar en diferentes zonas de la jerarquía de memoria, y pueden operar según los modos de direccionamientos que permita la CPU.
  • Aritméticas: como puedes imaginar, estas instrucciones se usan para realizar operaciones aritméticas sobre los operandos. Por ejempo, se puede usar una unidad ALU para realizar sumas, restas, multiplicaciones o divisiones sobre los bits binarios.
  • Lógicas: para realizar operaciones lógicas en la ALU, como pueden ser AN, OR, XOR, etc., sobre los bits binarios del operando.
  • Conversión: pueden ser similares a las dos anteriores, pero pueden realizar conversiones entre los tipos de datos soportados por la ISA.
  • Control: este otro tipo de instrucciones son muy importantes, y actúan directamente sobre el registro PC o Program Counter de la CPU. Este registro apunta a la siguiente instrucción a ejecutar de forma que el programa se ejecuta secuencialmente, instrucción tras instrucción. Sin embargo, con estos códigos se puede alterar esto para, por ejemplo, producir saltos condicionales, bucles, etc. También son aquellos que pueden encargarse de las syscall o llamadas del sistema, retorno de subrutinas, etc.
  • De E/S: en este caso se utilizan para realizar operaciones de entrada y salida. El sistema de E/S actúa como una memoria, usando direcciones en las que se puede leer para los periféricos de entrada y direcciones en las que se puede escribir para los periféricos de salidas. Todo mapeado para poder controlar diversos periféricos por parte de la CPU.

¿Qué es illegal op_code? (Instrucciones indocumentadas)

Un illegal op_code, también llamado instrucción no documentada, o código de operación no deseado, no es más que una instrucción de la CPU tal como hemos comentado en los apartados anteriores pero que no se menciona en ningún manual oficial por parte del diseñador o fabricante de la CPU. Esto es bastante misterioso y genera mucha desconfianza en algunos usuarios que analizan sus procesadores en busca de estas instrucciones indocumentadas. De hecho, en GitHub puedes encontrar algún programa para realizar este tipo de búsquedas…

Estos op_codes o instrucciones no documentadas pueden ser totalmente inofensivas, pero también podrían emplearse por códigos diseñados por el que las conoce con otras intenciones menos benignas. Y es que, aunque no estén documentadas y no sean empleadas por ningún compilador comercial, sí que tienen su función.

No es extraño encontrar instrucciones indocumentadas en cualquier CPU, ni tampoco registros que no se muestran en los manuales o que no están disponibles para el programador o son transparentes para éste, y que los diseñadores se reservan para tareas que no detallan o pensando en futuras funciones que se implementarán en las nuevas generaciones, o con el fin de realizar pruebas en los sample engineering.

Un poco de historia

Uno de los op_codes indocumentados más tempranos que se detectaron fue en la década de los 1970, en CPUs tan populares como la Intel 8086, la Zilog Z80 y el MOS Technology 6502. También se pueden nombrar los TM9900 de Texas Instruments, entre otros muchos casos.

En algunas de estas CPUs antiguas, estos op_codes existían debido al cableado o interconexiones de los transistores, permitiendo que se pudieran realizar otras operaciones que no estaban previstas por el diseñador. En los diseños más modernos, también hay instrucciones indocumentadas introducidas intencionadamente por el diseñador para su propio uso.

En algunas arquitecturas, estos códigos de operación ilegales no son más que una Trap para un controlador de errores. Sin embargo, aún pueden seguir existiendo códigos no verificados o no esperados que puedan estar presentes en algunas CPUs. Además, como es lógico, muchos usuarios empiezan a desarrollar su lado más paranóico y sospechan que también podrían estar ahí para algo, y no precisamente positivo para la seguridad…

En diseños de CPU como los Intel 80186, 80286 o los Motorola 68000, no se conocieron demasiadas instrucciones indocumentadas o no se usaron como en otros casos. Además, si una CPU está correctamente diseñada, cuando se topa con uno de estos códigos ilegales debería generar una exceción o condición de falla, para terminar con la aplicación que contiene este código indocumentado y que no se generen otros problemas.

Afortunadamente, si alguno de estos códigos de operación ilegales causase algún fallo recurrente, se podría parchear mediante la actualización del firmware o microcódigo.

En el panorama actual, a pesar de que compañías como Intel niegan o dan toda su garantía contra tales instrucciones, muchas investigaciones se han topado con instrucciones no documentadas mediante técnicas de fuzzing. Algunas de estas instrucciones indocumentadas se han encontrado en CPUs recientes tanto de Intel como de AMD, así también como en otras como pueden ser las M-Series de Apple (véase AMX).

Algunas instrucciones indocumentadas pueden ser parte de una familia o ISA, y se heredan a todos los procesadores derivados de ella, otras serán solo específicas de ciertas microarquitecturas o implementaciones.

Efectos de las instrucciones no documentadas

Entre los efectos de estos op_codes o instrucciones no documentados tenemos:

  • Algunas pueden ser simplemente accidentales, sin efectos útiles. Otras podrían incluso tener efectos indeseables, produciendo errores si se ejecutan.
  • También pueden usarse para acelerar algunas tareas críticas.
  • Otro efecto común puede ser la implementación para proteger a los chips de ingeniería inversa o clones de las CPUs que eran habituales en el pasado.
  • Por otro lado, también podrían ser mucho más oscuras que eso, y usarse en algunos casos para comprometer la seguridad, aunque por el momento no se ha observado ninguna de este tipo.
  • Incluso podrían estar ahí para realizar ciertas funciones durante las pruebas del chip o depuración.

Por otro lado, hay que destacar que estas instrucciones indocumentadas también podrían implicar otros riesgos, ya que al no estar documentadas o no conocerse su existencia, en futuras implementaciones o cambios de la CPU, podrían generar problemas. Esto ocurrió por ejemplo en el Apple II, cuando apareció el Apple IIc, que algunos videojuegos no funcionaban debido a que usaban una variante del 6502 conocida como 65c02, que eliminó estos códigos.

A día de hoy, muchos analizan sus CPUs en busca de estas instrucciones indocumentadas por pura curiosidad, o para descubrir posibles fallos o vulnerabilidades. En otros casos simplemente se emplean para poder diseñar emuladores de dicha CPU y crear sistemas exáctos…

Jaime Herrera

Jaime Herrera

Técnico electrónico y experto en el sector de los semiconductores y el hardware. Con una amplia y sólida trayectoria en el campo de la electrónica, he acumulado una extensa experiencia. Mi pasión por la tecnología y la informática me ha impulsado a dedicar décadas de mi vida al estudio y desarrollo de soluciones en este fascinante sector. Como técnico electrónico, he tenido el privilegio de trabajar en una variedad de proyectos y desafíos, lo que me ha permitido adquirir un profundo conocimiento y experiencia en la creación, diseño y mantenimiento de dispositivos electrónicos.

>
Guía Hardware
Logo