Rutas
/
Lean
Lean
/
Ejercicios
/
Ensamblar
Ensamblar

Ensamblar

Difícil

Instrucciones

En este ejercicio, definirás la sintaxis y el modelo de ejecución de un pequeño lenguaje inspirado en el lenguaje ensamblador x86-64.

El objetivo es formalizar cómo se escribe, se analiza y se ejecuta el código dentro de un entorno restringido.

Modelo de ejecución

Tu código ensamblador se escribirá dentro de una construcción especial:

let program := assemble!(
    -- assembly code here
)

Esta construcción debe producir un programa, que simula una función que ejecuta el código ensamblador y devuelve un valor. Luego, este programa se invoca con la siguiente sintaxis, donde a, b, c, etc. son argumentos:

let result := program(a, b, c, ...)

Todos los argumentos y el valor devuelto son enteros de 64 bits con signo. Se permite un máximo de 6 argumentos.

Registros

El valor devuelto y todos los argumentos se pasan en registros. Tu lenguaje debe admitir los siguientes registros:

registro rol
rdi primer argumento
rsi segundo argumento
rdx tercer argumento
rcx cuarto argumento
r8 quinto argumento
r9 sexto argumento
rax valor devuelto

Los registros empiezan con un valor predeterminado de 0, a menos que se usen para pasar argumentos a la función.

Por ejemplo, en el siguiente programa todos los registros tienen un valor de 0 salvo rdi, que se inicializa con 10, y rsi, que se inicializa con -20:

program(10, -20)

El valor devuelto del programa siempre se almacena en rax.

Note

Los nombres de los registros no distinguen entre mayúsculas y minúsculas. Esto significa que rax, RAX y rAx se refieren todos al mismo registro.

Código ensamblador

Cada línea del código ensamblador puede adoptar una de estas dos formas:

  • Las etiquetas marcan lugares concretos del programa que pueden usar algunas instrucciones.
  • Las instrucciones representan operaciones que ejecuta el programa.

Salvo que alguna instrucción lo modifique, el flujo de ejecución del programa avanza de forma lineal. Esto significa que una línea se ejecuta por completo antes que la línea siguiente.

Etiquetas

Las etiquetas tienen la siguiente sintaxis:

<label>:

No alteran el valor de ningún registro ni tienen ningún efecto sobre el programa aparte de marcar lugares concretos del código para que las instrucciones puedan usarlos.

Note

Las etiquetas distinguen entre mayúsculas y minúsculas. Esto significa que Start, start y sTart son etiquetas distintas.

Instrucciones de dos operandos

La mayoría de las instrucciones tienen la siguiente sintaxis:

<opcode> <destination>, <source>

El opcode indica la operación que se ejecuta, usando los valores de los operandos destination y source. El resultado de la operación se almacena en el operando destination.

Por ejemplo, la instrucción add suma los valores de los operandos destination y source y almacena ese resultado en el operando destination.

El operando destination es siempre un registro, mientras que el operando source puede ser un registro o un número literal.

Esta es una lista de las instrucciones que tu programa debe admitir:

opcode operación realizada
mov destination := source
add destination := destination + source
sub destination := destination - source
mul destination := destination * source
div destination := destination / source
xor destination := destination ^^^ source
and destination := destination &&& source
or destination := destination ||| source
shl destination := destination <<< source
shr destination := destination >>> source

Además de esas, tu programa debe admitir la instrucción cmp de dos operandos.

Esta instrucción no modifica ningún registro, sino que compara los operandos destination y source y fija un estado interno del programa a una de estas tres opciones:

  • mayor que, si destination > source
  • igual, si destination == source
  • menor que, si destination < source

Cómo lleves la cuenta de este estado internamente es cosa tuya.

Instrucciones de un operando

Hay algunas instrucciones que alteran el flujo del programa y transfieren la ejecución a otro punto del código. Se denominan instrucciones de salto.

Todas ellas toman un solo operando, que es una etiqueta que indica el destino del salto, es decir, el punto del código donde continuará la ejecución:

<opcode> <label>

La instrucción jmp siempre realiza el salto a la etiqueta de destino.

Otras instrucciones de salto solo saltan si el estado interno del programa tiene un valor concreto. Esto significa que suelen ir precedidas de una instrucción cmp.

Estas son las instrucciones de salto que tu programa debe admitir:

instrucción operación realizada
jmp salto incondicional. El salto se realiza siempre
je salta si el estado interno es igual
jl salta si el estado interno es menor que
jg salta si el estado interno es mayor que
Note

Los códigos de operación de las instrucciones, tanto las de dos operandos como las de un operando, no distinguen entre mayúsculas y minúsculas. Esto significa que add, ADD y aDd se refieren todos a la misma instrucción.

Editar en GitHub El enlace se abre en una ventana o pestaña nueva
Lean Exercism

¿Listo para empezar Ensamblar?

Regístrate en Exercism para aprender y dominar Lean con 100 ejercicios y mentoría humana real, todo gratis.