LEGv8
LEGv8 es un conjunto de instrucciones. Es una versión simplificada y un subconjunto de ARMv8.
Convención de registros
- X0 - X7: Argumentos de entrada/salida de funciones.
- X8: Resultado indirecto de localización de registro.
- X9 - X15: Registros temporales.
- X16 - X17: Sobreescrito por el sistema como scratch register.
- X18: Registro de uso especial del OS o temporal
- X19 - X27: Registros de uso general.
- X28: Puntero a stack.
- X29: Puntero a frame.
- X30: Registro de enlace (link register).
- XZR: Valor constante- 0.
Instrucciones
- ADD: Suma de registros
- ADDI: Suma con valor constante
- SUB: Resta de registros
- SUBI: Resta con valor constante
- AND: Operación AND entre registros
- ANDI: Operación AND con valor constante
- ORR: Operación OR entre registros
- EOR: Operación XOR entre registros
- ORRI: Operación OR con valor constante
- LSL: Recibe una constante- #cy recibe un registro para multiplicarlo por- 2^c.
 Desplaza a la izquierda el registro- X1- #cveces y lo almacena en- X2.
- LSR: Recibe una constante- c, desplaza a la derecha el registro- X1- #cveces y lo almacena en- X2.
- LDUR: Copia al registro- X1el contenido en la posición de memoria direccionada por- X2sumado a la constante- #c(memoria doubleword)
- STUR: Copia el contenido del registro- X1en la posición de memoria direccionada por- X2sumado a la constante- #c(memoria doubleword)
- LDURSW: Lo mismo que- LDUR(memoria word)
- STURSW: Lo mismo que- STUR(memoria word)
- LDURB: Lo mismo que- LDUR(memoria byte)
- STURB: Lo mismo que- STUR(memoria byte)
- MOVZ: Mueve un valor inmediato a un registro (cero extendido)
- MOVK: Mueve un valor inmediato a un registro y lo combina con el contenido del registro.
Operaciones
Operaciones inmediatas (valores constantes)
// Ejemplo de código C
f = g + 5;Sean g => X21 y f => X19, la instrucción se traduce a:
ADDI X19, X21, #5Operaciones en registros
Las operaciones en registros se hacen de la siguiente forma
// Ejemplo de código C
f = (g + h) - (i + j);Solo se puede operar sobre dos registros a la vez, por lo que se requieren valores temporales:
ADD X9, X21, X22 // g + h
ADD X10, X22, X23 // i + j
SUB X19, X9, X10 // f = (g + h) - (i + j)Operaciones en memoria
Operar en datos almacenados en memoria es más lento que operar en registros, ya que requieren más instrucciones:
// Ejemplo de código C
a[12] = h + a[8];Sean h => X21 y a => X22, la instrucción se traduce a:
LDUR X9, [X22, #64] 
ADD X9, X21, X9
STUR X9, [X22, #96]Cada elemento de memoria es de  bits, para obtener los  bits necesarios de cada elemento del arreglo a hay que usar un offset de  bits.
Ejercicios resueltos - Operaciones
Escribir las secuencias de assembler LEGv8 en base al código C:
1.
// A)
f = g + h + i + j;
 
// B)
f = g + (h + 5);
 
// C)
f = (g + h) + (i + j);Para este ejercicio, se asignan a las variables f, g, h, i, j los registros X0, X1, X2, X3, X4, respectivamente:
// A)
ADD X0, X1, X2   
ADD X0, X0, X3   
ADD X0, X0, X4   
   
// B)
ADD X0, X0, X1    
ADDI X0, X2, #5  
  
// C)
ADD X9, X1, X2   
ADD X10, X3, X4
ADD X0, X9, X10  2.
// A) 
f = -g - f;
 
// B)
f = g + (-f - 5);Para este ejercicio, se asignan a las variables f, g los registros X0, X1, respectivamente:
// A) 
ADD X0, X1, X0
SUB X0, XZR, X0  
  
// B) 
ADDI X0, X0, #5 
SUB X0, X1, X0  3.
// A)
f = -g - a[4];
 
// B)
b[8] = a[i - j]; Para este ejercicio, se asignan a las variables f, g, i, j los registros X0, X1, X2, X3, respectivamente.
La dirección base de los arrays a, b se almacenan en los registros X6, X7
// A)
LDUR X0, [X6, #32]   // f = a[4]
ADD X0, X0, X1       // f = (a[4]) + g 
SUB X0, XZR, X0      // f = 0 - (a[4] + g)
  
// B)
SUB X9, X2, X3       // X9 = i - j 
LSL X9, X9, #3       // X9 = (i - j) * 8 
ADD X10, X6, X9      // X10 = &a + [(i - j) * 8] 
LDUR X11, [X10, #0]  // X11 = a[i - j]
STUR X11, [X7, #64]  // b[8] = a[i - j]4.
Usar MOVZ, MOVK para cargar los registros:
{X0 = 0x1234000000000000}
{X1 = 0xBBB0000000000AAA} 
{X2 = 0xA0A0B1B10000C2C2} 
{X3 = 0x0123456789ABCDEF}MOVZ X0, 0x1234, LSL 48  // 0x1234000000000000
  
MOVZ X1, 0xBBB, LSL 52   // 0xBBB0000000000000
MOVK X1, 0xAAA, LSL 00   // 0xBBB0000000000AAA
  
MOVZ X2, 0xA0A0, LSL 48  // 0xA0A0000000000000
MOVK X2, 0xB1B1, LSL 32  // 0xA0A00000B1B10000
MOVK X2, 0xC2C2, LSL 00  // 0xA0A0B1B10000C2C2
  
MOVZ X3, 0x0123, LSL 48  // 0x0123000000000000
MOVK X3, 0x4567, LSL 32  // 0x0123456700000000
MOVK X3, 0x89AB, LSL 16  // 0x0123456789AB0000
MOVK X3, 0xCDEF, LSL 00  // 0x0123456789ABCDEFCondicionales y saltos
Mediante el uso de
CBZyCBNZse puede hacer un salto condicional.
CBZrecibe un registro y una rama, y si el registro es0salta a la rama.
CBNZrecibe un registro y una rama, y si el registro es distinto de0salta a la rama.
Bes un salto a una rama.
Ejemplo: bloque if en C:
if (i == j) {
  f = g + h;
} else {
  f = g - h;
}Asignamos a las variables f, g, h, i, j los registros X0, X1, X2, X3, X4, respectivamente:
      SUB X9, X3, X4  // i - j
      CBNZ X9, Else   // i != j  ⇒  salta a Else
      ADD X0, X1, X2  // f = g + h
      B Exit          // salta a Exit
Else: SUB X9, X1, X2  // f = g - h
Exit: ...Ejemplo: bloque while en C:
while (save[i] == k) { 
  i += 1;
}Asignamos a las variables i, k los registros X0, X1, respectivamente.
La dirección base del array save se almacena en el registro X2:
      LSL X9, X0, #3    // i * 8
      ADD X9, X9, X2    // &save[i]
Loop: LDUR X10, [X9]    // save[i]
      CBNZ X10, End     // save[i] != k  ⇒  salta a End
      ADDI X0, X0, #1   // i += 1
      B Loop
End:  ...Operaciones condicionales
Es posible modificar los valores de los flags
N, Z, C, Vmediante el uso de una instrucción con sufijoS(ADDS, ADDIS, SUBS, SUBIS, ANDS, ANDIS...)
Con la comparación, se puede hacer un salto condicional conB.EQ,B.NE,B.GE,B.LT,B.GT,B.LE...
Ejemplo: bloque if en C:
if (a > b) {
  a += 1;
}Asignamos a las variables a, b los registros X0, X1, respectivamente:
      SUBS X9, X0, X1   // a - b
      B.GE Else         // a <= b  ⇒  salta a Else
      ADDI X0, X0, #1   // a += 1
Else: ...También se puede usar CMP, CMPI para comparar sin almacenar el resultado en un registro:
      CMP X0, X1        // comparar a, b
      B.GE Else         // a <= b  ⇒  salta a Else
      ADDI X0, X0, #1   // a += 1
Else: ...Formato y ensamblado de instrucciones
Todas las instrucciones tienen un formato de bits, donde la distribución de los bits depende del tipo de instrucción.
Instrucciones de tipo R
Las instrucciones de tipo R son aquellas que operan y reciben registros como argumentos.
- opcode: la instrucción a ejecutar (por ejemplo, ADD,SUB,AND,ORR, etc.)
- Rm: segundo registro operando.
- shamt: desplazamiento (shift amount).
- Rn: primer registro operando.
- Rd: registro destino (donde se almacena el resultado de la operación).
| Opcode | Rm | Shamt | Rn | Rd | 
|---|---|---|---|---|
| bits | bits | bits | bits | bits | 
Instrucciones de tipo D
Las instrucciones de tipo D son aquellas que transfieren datos entre memoria y registros.
| Opcode | address | op2 | Rn | Rt | 
|---|---|---|---|---|
| bits | bits | bits | bits | bits | 
- address: offset de la dirección de memoria.
El valor de address debe ser el valor de la constante en base ,
agregando los bits necesarios para llegar a  bits.
- op2: expande el opcode (siempre debe estar seteado a- 00).
Instrucciones de tipo I
Las instrucciones de tipo I son aquellas que operan con un valor inmediato.
| Opcode | immediate | Rn | Rd | 
|---|---|---|---|
| bits | bits | bits | bits | 
- immediate: valor inmediato (constante). (de a )
Instrucciones de tipo IM
Las instrucciones de tipo IM son aquellas que mueven contenidos entre registros.
| Opcode | LSL | MOV immediate | Rd | 
|---|---|---|---|
| bits | bits | bits | bits | 
- LSL: desplazamiento a la izquierda (shift left).
- MOV immediate: valor inmediato (constante). (de a )
Instrucciones de tipo B
Las instrucción de tipo B (solo
B) realiza saltos directos a otras instrucciones.
| Opcode | BR address | 
|---|---|
| bits | bits | 
El valor de BR address es un binario cuyo valor es la cantidad de saltos realizados para llegar a la rama seleccionada (colocando los bits necesarios para llegar a )
Si se realizan tres saltos hacia adelante, su valor sería 00000000000000000000000011 = 3
Si se realizan tres saltos hacia atrás, su valor sería 11111111111111111111110011 = -3
Instrucciones de tipo CB
Las instrucciones de tipo CB son aquellas que realizan saltos condicionales a otras instrucciones.
| Opcode | COND BR address | Rt | 
|---|---|---|
| bits | bits | bits | 
El criterio para poner el valor de COND BR address es el mismo que BR address, ajustando a  bits.