ISA, ARM, x86… ¿qué es el set de registros e instrucciones de una CPU?

ISA, ARM, x86… ¿qué es el set de registros e instrucciones de una CPU?

Josep Roca

¿Alguna vez te has preguntado cuál es el motivo que lleva a que un programa compilado para funcionar en las CPU x86 para PC, no funcione en una CPU ARM por ejemplo? ¿Qué es lo que hace que un programa sea compatible con una familia de procesadores concreta y con otras no? ¿Qué son los registros y cual es su función? En este artículo os explicamos lo que son los registros y las instrucciones de una CPU para que podáis comprenderlo.

Muchas veces hemos hablado de que los procesadores cuentan con un conjunto de instrucciones concreto, o de que en un nuevo procesador se ha añadido un conjunto de instrucciones. Vamos a ver qué es lo que esto quiere decir.

¿Qué es una instrucción?

Una instrucción no es más que una acción que mandamos a hacer en un procesador. Las instrucciones pueden ser operaciones aritméticas con diferentes tipos de datos como coma flotante, enteros, vectorial, escalar, operaciones lógicas, operaciones de movimientos de datos, operaciones de movimiento de bits (donde un bit es cambiado de posición), operaciones de salto, etc.

Esas mismas instrucciones se dividen en otros sub-tipos según donde se encuentren los datos. Por ejemplo, algunas instrucciones permiten operar con los datos que se encuentran en los registros en ese momento, mientras que en otros casos hemos de marcar la dirección de memoria en la que se encuentra el dato (modo directo) o la dirección de la dirección de memoria (modo indirecto).

Cómo la CPU lee las instrucciones en código binario

Independientemente de cuál sea la CPU que esté utilizando nuestro sistema, todas ellas leen el código binario de una manera particular correspondiente a su familia. Lo que hacen es tomar una cantidad de determinada de bits del código binario que están ejecutando e interpretan su significado según la disposición de éste. Toda instrucción está codificada de la siguiente manera: los primeros dígitos corresponden al código de la instrucción y cómo se ha de ejecutar ésta, y los últimos bits son el dato mismo o dónde se encuentra el dato sobre el que queremos realizar la instrucción.

A los conjuntos de registros e instrucciones de las CPU se les llama ISA (Instruction Set Architecture) y todos bajo la misma ISA utilizan la misma codificación de las instrucciones y por tanto el mismo código binario para ellas.

Relación conjunto de instrucción con el lenguaje ensamblador

Set Instrucciones x86

Todas las familias de procesadores tienen un lenguaje ensamblador común dentro de la misma, cuyas instrucciones tienen una correlación 1:1 con el conjunto de registros e instrucciones de dicha familia de procesadores. En la tabla de arriba podéis ver la relación entre las diferentes instrucciones del lenguaje ensamblador de los x86 con su código de instrucción, el cual en la tabla se encuentra expresado en hexadecimal.

Hay que tener en cuenta que continuamente se añaden instrucciones nuevas a las ISAs, lo que lleva a que programas muy nuevos que utilicen expresamente esas nuevas instrucciones solo funcionen en procesadores que las soporten. En general, los conjuntos de instrucciones se mantienen estables en el tiempo con pocos cambios, pero de tanto en cuando se introducen instrucciones para ciertos mercados específicos que acaban formando parte del estándar o son descartadas después.

También existe el caso de nuevas instrucciones más eficientes que las ya existentes, pero en el que no se eliminan dichas instrucciones del conjunto por existir una gran cantidad de software dependiente de ellas en el mercado.

RISC vs CISC vs Post-RISC

Los procesadores RISC tienen pocas instrucciones por lo que necesitan suplir la falta de instrucciones por otras más complejas, pero a cambio consiguen una mayor velocidad a la hora de ejecutarlas debido a su ligereza. Los procesadores CISC en cambio tienen conjuntos de instrucciones mucho más complejos que requieren una construcción mas compleja del hardware, pero a cambio realizan dichas instrucciones en menos ciclos.

Dicha diferencia, aunque polémica en su día, ya no lo es debido a que desde la aparición del Pentium Pro en PC pasamos a la época Post-RISC en la que pese a que los programas utilizan un conjunto de registros e instrucciones éstos son convertidos en un microcódigo de instrucciones más simples en el proceso, permitiendo que arquitecturas CISC se puedan comportar como arquitecturas RISC y alcanzar grandes velocidades de reloj utilizando instrucciones complejas.

Los registros de una CPU

Registros e instrucciones CPU

Los registros son la memoria más cercana a un procesador que existe y por tanto la más rápida; se trata de memorias muy pequeñas que pueden ser manipuladas de manera directa por la unidad de control del procesador. Son utilizados para realizar todo tipo de tareas comunes y no solo para realizar operaciones aritméticas.

Los registros más comunes en una CPU independientemente de su ISA son:

  • Registros del tipo acumulador: se utiliza para operaciones aritméticas. Cada familia tiene una cantidad diferente de registros del tipo acumulador.
  • Registros de acceso a la memoria: contienen la dirección de memoria de los datos a los que queremos acceder de la RAM.
  • Registros de datos a o desde la memoria: contienen el datos copiados desde la memoria (lectura) o que se va a escribir a una dirección de memoria concreta (escritura).
  • Registros de propósito general: se trata de registros de memoria sin una utilidad concreta pero que nos sirven para almacenar datos para ser invocados lo más rápidamente posible.
  • Contador de programa: indica la siguiente instrucción a ejecutar; las instrucciones de salto las modifican cuando no se quiere acceder a a la siguiente instrucción sino a otra parte del programa. En cada ciclo de instrucción completo se incrementa la dirección de memoria en 1 y esta asociado al bus de direcciones del procesador.

Algunos de los registros de CPU como por ejemplo el registro contador de programa, el cual indica cuál es la siguiente dirección de memoria a la que apunta el procesador, se encuentran en todas las CPUs y otros tipos de procesadores con la capacidad de ejecutar programas mientras que otros registros son únicos de cada conjunto de registros e instrucciones, lo que hace la correlación 1:1 entre diferentes ISAs sea casi imposible.

Incluso si tuviéramos un conversor 1:1 del código de las instrucciones seguiríamos teniendo problemas porque aunque dos procesadores puedan tener una misma instrucción de suma nos podemos encontrar con que la forma de utilizar los registros y los registros que usan son distintos y que incluso haya registros que se encuentran  en una familia y no en otros. Un ejemplo de estas dificultades lo encontraron tanto Microsoft como Qualcomm a la hora de adaptar Windows 10 a ARM para que todas las aplicaciones x86 funcionasen sin problemas en una CPU ARM.

No obstante, hay soluciones como el hecho de utilizar un software de traducción de instrucciones. Dicho software traslada el código binario a un código intermedio paro luego trasladarlo al código binario del procesador objetivo en que el que queremos correr la aplicación. Obviamente este proceso es mucho más lento y solo es recomendable para ejecutar software muy antiguo de familias de procesadores inexistentes en el mercado.