Instruction Set Architecture
Instruction Set Architectures
Una Instruction Set Architecture
(ISA
) especifica la sintaxis y la semántica del lenguaje ensamblador en cada arquitectura. No es solo una sintaxis diferente, sino que está integrada en el diseño central de un procesador, ya que afecta la forma y el orden en que se ejecutan las instrucciones y su nivel de complejidad. ISA
consiste principalmente en los siguientes componentes:
- Instructions
- Registers
- Memory Addresses
- Data Types
Component | Description | Example |
---|---|---|
Instructions |
La instrucción que se procesará en el formato opcode operand_list . Generalmente hay 1, 2 o 3 operandos separados por comas. |
add rax, 1 , mov rsp, rax , push rax |
Registers |
Se utilizan para almacenar operandos, direcciones o instrucciones temporalmente. | rax , rsp , rip |
Memory Addresses |
La dirección en la que se almacenan datos o instrucciones. Puede apuntar a memoria o registros. | 0xffffffffaa8a25ff , 0x44d0 , $rax |
Data Types |
El tipo de datos almacenados. | byte , word , double word |
Estos son los componentes principales que distinguen diferentes ISA's
y lenguajes ensambladores. Cubriremos cada uno de ellos en más profundidad en las siguientes secciones y aprenderemos cómo usar varias instrucciones.
Existen dos principales Instruction Set Architectures que son ampliamente utilizadas:
Complex Instruction Set Computer
(CISC
) - Utilizado en procesadoresIntel
yAMD
en la mayoría de las computadoras y servidores.Reduced Instruction Set Computer
(RISC
) - Utilizado en procesadoresARM
yApple
, en la mayoría de los teléfonos inteligentes y algunas laptops modernas.
Veamos los pros y contras de cada uno y las principales diferencias entre ellos.
CISC
La arquitectura CISC fue una de las primeras ISA's
desarrolladas. Como su nombre lo sugiere, la arquitectura CISC favorece instrucciones más complejas para ser ejecutadas al mismo tiempo y así reducir el número total de instrucciones. Esto se hace para depender lo más posible de la CPU combinando instrucciones menores en instrucciones más complejas.
Por ejemplo, supongamos que queremos sumar dos registros con la instrucción 'add rax, rbx
'. En este caso, un procesador CISC puede hacer esto en un solo ciclo de instrucción 'Fetch-Decode-Execute-Store', sin tener que dividirlo en múltiples instrucciones para obtener rax
, luego obtener rbx
, luego sumarlos y luego almacenarlos en rax
, cada uno de los cuales tomaría su propio ciclo de instrucción 'Fetch-Decode-Execute-Store'.
Dos razones principales impulsaron esto:
- Permitir que más instrucciones se ejecuten al mismo tiempo diseñando el procesador para ejecutar instrucciones más avanzadas en su núcleo.
- En el pasado, la memoria y los transistores eran limitados, por lo que se prefería escribir programas más cortos combinando múltiples instrucciones en una sola.
Para habilitar a los procesadores a ejecutar instrucciones complejas, el diseño del procesador se vuelve más complicado, ya que está diseñado para ejecutar una gran cantidad de instrucciones complejas diferentes, cada una de las cuales tiene su propia unidad para ejecutarla.
Además, aunque se necesita un solo ciclo de instrucción para ejecutar una sola instrucción, como las instrucciones son más complejas, cada ciclo de instrucción toma más ciclos de reloj. Esto lleva a un mayor consumo de energía y calor para ejecutar cada instrucción.
RISC
La arquitectura RISC favorece dividir las instrucciones en instrucciones menores, y así la CPU está diseñada solo para manejar instrucciones simples. Esto se hace para delegar la optimización al software escribiendo el código ensamblador más optimizado.
Por ejemplo, la misma instrucción anterior add r1, r2, r3
en un procesador RISC obtendría r2
, luego obtendría r3
, los sumaría y finalmente los almacenaría en r1
. Cada una de estas instrucciones toma un ciclo completo 'Fetch-Decode-Execute-Store', lo que lleva, como se puede esperar, a un mayor número total de instrucciones por programa y, por lo tanto, un código ensamblador más largo.
Al no admitir varios tipos de instrucciones complejas, los procesadores RISC solo admiten un número limitado de instrucciones (~200
) en comparación con los procesadores CISC (~1500
). Entonces, para ejecutar instrucciones complejas, esto debe hacerse a través de una combinación de instrucciones menores en Assembly.
Se dice que podemos construir una computadora de propósito general con un procesador que solo admita una instrucción. Esto indica que podemos crear instrucciones muy complejas utilizando únicamente la instrucción sub
. ¿Puedes pensar cómo se podría lograr esto?
Por otro lado, una ventaja de dividir instrucciones complejas en menores es tener todas las instrucciones con la misma longitud, ya sea de 32 bits o 64 bits. Esto permite diseñar la velocidad del reloj de la CPU en función de la longitud de la instrucción, de modo que ejecutar cada etapa en el ciclo de instrucción siempre tome exactamente un ciclo de reloj de máquina.
El siguiente diagrama muestra cómo las instrucciones CISC toman una cantidad variable de ciclos de reloj, mientras que las instrucciones RISC toman una cantidad fija:
Ejecutar cada etapa de instrucción en un solo ciclo de reloj y solo ejecutar instrucciones simples lleva a que los procesadores RISC consuman una fracción de la energía consumida por los procesadores CISC, lo que hace que estos procesadores sean ideales para dispositivos que funcionan con baterías, como teléfonos inteligentes y laptops.
CISC vs. RISC
La siguiente tabla resume las principales diferencias entre CISC y RISC:
Area | CISC | RISC |
---|---|---|
Complexity |
Favorece instrucciones complejas | Favorece instrucciones simples |
Length of instructions |
Instrucciones más largas - Longitud variable 'múltiplos de 8 bits' | Instrucciones más cortas - Longitud fija '32-bit/64-bit' |
Total instructions per program |
Menos instrucciones totales - Código más corto | Más instrucciones totales - Código más largo |
Optimization |
Depende de la optimización por hardware (en CPU) | Depende de la optimización por software (en Assembly) |
Instruction Execution Time |
Variable - Múltiples ciclos de reloj | Fijo - Un ciclo de reloj |
Instructions supported by CPU |
Muchas instrucciones (~1500) | Pocas instrucciones (~200) |
Power Consumption |
Alto | Muy bajo |
Examples |
Intel, AMD | ARM, Apple |
En el pasado, tener un código ensamblador más largo debido a un mayor número total de instrucciones por programa era una desventaja significativa para los procesadores RISC debido a los recursos limitados en memoria y almacenamiento. Sin embargo, hoy en día esto ya no es un problema tan grande, ya que la memoria y el almacenamiento no son tan costosos ni limitados como solían ser.
Con ensambladores y compiladores escribiendo código extremadamente optimizado a nivel de software, los procesadores RISC se están volviendo más rápidos que los procesadores CISC, incluso al ejecutar y procesar aplicaciones pesadas, mientras consumen mucha menos energía.
Todo esto está haciendo que los procesadores RISC sean más comunes en los últimos años. RISC podría convertirse en la arquitectura dominante en los próximos años. Pero, mientras hablamos, la gran mayoría de las computadoras y servidores que estaremos pentesteando están ejecutándose en procesadores Intel/AMD con la arquitectura CISC, lo que hace que aprender ensamblador CISC sea nuestra prioridad. Dado que los conceptos básicos de todas las variantes de lenguaje Assembly son bastante similares, aprender ARM Assembly debería ser más sencillo después de completar este módulo.