Tracks
/
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 de retorno son enteros con signo de 64 bits. Se permite un máximo de 6 argumentos.

Registros

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

registro rol
rdi 1.er argumento
rsi 2.º argumento
rdx 3.er argumento
rcx 4.º argumento
r8 5.º argumento
r9 6.º argumento
rax valor de retorno

Los registros comienzan 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, con la excepción de rdi, que se inicializa con 10, y rsi, que se inicializa con -20:

program(10, -20)

El valor de retorno 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 al mismo registro.

Código ensamblador

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

  • Etiquetas: marcan lugares específicos del programa para que algunas instrucciones los usen.
  • Instrucciones: representan las operaciones que ejecuta el programa.

A menos que alguna instrucción lo modifique, el flujo de ejecución del programa avanza de forma lineal. Esto significa que una línea anterior se ejecuta por completo antes de que se ejecute 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 específicos del código para que las instrucciones los usen.

Note

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

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 este 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 instrucciones que tu programa debe admitir:

código de operación 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

Aparte 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 establece un estado interno del programa en una de tres opciones:

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

Depende de ti cómo llevar internamente el seguimiento de este estado.

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 llaman instrucciones de salto.

Todas 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 salta a la etiqueta destino.

Las demás instrucciones de salto solo hacen el salto si el estado interno del programa está establecido en un valor específico. Esto significa que normalmente van precedidas por 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 siempre se realiza
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, ya sean de dos operandos o de un operando, no distinguen entre mayúsculas y minúsculas. Esto significa que add, ADD y aDd se refieren a la misma instrucción.

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

¿Todo listo para empezar Ensamblar?

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