WinAli: CPU virtual para comprender el lenguaje ensamblador

8

WinAli es un ensamblador modelo para Windows. Emula una CPU real y está destinada a ayudar a los estudiantes a aprender y comprender el lenguaje ensamblador.

Artículo de Wikipedia en alemán: http://de.wikipedia.org/wiki/WinAli (no hay ningún artículo en inglés en este momento)

En caso de que quiera probar su salida producida: Enlace a Google Drive (el programa en sí está en alemán pero es fácil de usar incluso si no entiende alemán)

Alguna información sobre WinAli (datos y sintaxis)

Tipos de datos:

El único tipo de datos en WinAli es un "entero" de 2 bytes de longitud, que de hecho es un Smallint o corto . Por lo tanto, no tiene que ocuparse de los tipos correctos. Esto también se redondea al dividir.

Variables y constantes:

Las variables se definen así después de los comandos:

name DS F
  • nombre es obviamente el nombre de la variable
  • DS es la palabra clave para una nueva variable
  • F define la longitud de la variable en bits; esto es de base cero y hexadecimal, entonces F = 16 bits

Las constantes son muy similares:

name DC value
  • nombre es simplemente el nombre de la constante
  • DC es la palabra clave para una nueva constante
  • valor es el valor asignado a esa constante, por ejemplotwo DC '2'
  • No necesita especificar constantes al final del código. También puede escribirlos en línea con la LDAoperación (cargar), por ejemplo LDA 0,'2'. Esto carga "2" en el registro 0 (el acumulador).
Sintaxis:

El código está alineado en 4 columnas que están separadas por un espacio o pestaña:

label command params comment
  • La etiqueta se usa para el b labelcomando ( goto label) y a menudo se omite.
  • Comando uno de los comandos enumerados a continuación.
  • params uno o dos parámetros con al menos un registro y si es necesario otro registro, variable, pila o dirección; Estos parámetros están separados por una coma ( ,).
  • comentarios (opcional) un comentario con el prefijo ;o *hasta el final de la línea.

Código de referencia pequeño:

Hay más comandos, pero para este desafío solo necesitas esos:

  • INI A Almacena la siguiente entrada del usuario en variable A
  • OUTI ADa como resultado el valor que Acontiene la variable . No puede usar un registro aquí por alguna razón.
  • LDA 0,ACarga el valor de Aen el registro 0
  • STA 0,A Almacena el valor del registro 0 en la variable A
  • ADD 0,AAgrega el valor de Aal valor del registro 0
  • SUB 0,AMultiplica el valor de Acon el valor del registro 0
  • DIV 0,ADivide el valor de Apor el valor del registro 0
  • EOJDefine el final del trabajo, es decir, el código ejecutable. Las declaraciones variables y constantes comienzan después de esta marca.

No se necesita explícitamente para este desafío:

  • program START 0Establece la primera dirección que se ejecutará en 0, es decir, la siguiente línea ( programes solo el nombre del programa pero es necesario para el compilador)
  • END program Finaliza el programa, es decir, deja de ejecutarse, incluso si otras operaciones siguieran

Tu reto!

Escriba un programa o script que tome una expresión matemática con números y variables constantes y genere el código WinAli que toma todas las variables como entrada y genera el resultado de esa expresión.

  • No necesita generar los comandos STARTyEND
  • Aunque hay 16 registros definidos en WinAli, solo usamos el registro 0, que es el acumulador para todos los cálculos
  • No puede usar dos variables como parámetros de un comando. Tienes que guardar todos tus resultados en el acumulador (registro 0)
  • La entrada siempre tiene la forma de cualquiera x:=(a+b)/co simplemente (a+b)/c, usted decide
  • Solo necesita cuidarlo + - * / (ADD, SUB, MUL, DIV), por lo que no hay cálculos complejos como raíces, cuadrados o incluso seno
  • Consejo: Intente extraer primero expresiones simples con solo 2 argumentos, por ejemplo, a:=a+bluegox:=a/c
  • Consejo: Su programa puede usar variables adicionales (auxiliares) si no puede sobrescribir variables que no se usan más adelante en su código. Defínalos como h1 DS F.
  • Consejo: las líneas vacías son inútiles. Intenta evitarlos. (Realmente no los necesitas)

Ejemplo:

Expresión matemática:
 x: = (a + b) * c

Salida esperada (las líneas vacías son para una lectura más fácil):
    INI a
    INI b
    INI c

    LDA 0, a
    AGREGAR 0, b
    MUL 0, c
    STA 0, a

    OUTI a
    EOJ
un DS F
b DS F
c DS F

Puntuación:

Su puntaje se define por la longitud de su código + la longitud de la salida de las siguientes expresiones:

x:=a+b+c*c/d

x:=(a+b)/c-d

x:=a-b*c-d/e

x:=2*a-b*c+d
  • -10% si su código puede manejar menos unario en expresiones.

En caso de empate, gana la respuesta que produce el código WinAli que funciona más brevemente.

Las soluciones no pueden ser codificadas de ninguna manera. Validaré cada respuesta con expresiones adicionales para asegurarme de que su respuesta sea correcta.

Árbol Gigante
fuente
¿Qué es exactamente una expresión matemática? Por ejemplo, ¿se permiten constantes negativas? Unario menos? ¿Nombres de variables más largos que una letra?
nutki
¿Las directivas de entrada (INI x) deben seguir algún orden específico?
nutki
@nutki una expresión matemática se entiende como una simple x = a + b, por lo que no se pueden resolver ecuaciones complejas, se permiten constantes negativas, los nombres de variables pueden tener más de una letra (ab no es a * b), INI x se puede poner donde siempre que lo desee, no se necesita un orden específico, ya que almacena la siguiente entrada en la variable give, pero sería bueno si siguen el orden az en lugar de ser aleatorio
GiantTree
@nutki por unario menos quieres decir cosas como MUL 0,-a? esto no es posible porque no hay direcciones negativas ( aes solo un puntero a un valor), pero puede restar el valor de 0 para obtener la representación negativa ( SUB 0,a) y luego trabajar con este valor negativo; incluso puede almacenar esto en la variable original.
GiantTree
Quise decir unario menos en la expresión de entrada, por ejemplo, x:=-a*bo x:=a/-(b+c). Dado que el orden de entrada no está especificado, supongo que tenemos que usar los mismos nombres de variables en el código WinAli, ¿es ese el caso? ¿Con esas restricciones hay identificadores que nunca están en la entrada? Por ejemplo, ¿puede h1ser un nombre de variable de entrada?
nutki

Respuestas:

4

Perl 5: 948, código 355 + salida 593

Después de jugar al golf. La versión anterior más corta no se analizó correctamente (a+b)-4*c.

%m=split'\b','-SUB+ADD/DIV*MUL<LDA>STA';$i='(\w+|(?<!\w|\))-\d+)';
$_=<>;@x{@y=/([a-z]\w*)/gi}=@y;print"\tINI $_
"for@x=keys%x;
$f=$_,$x.="<$&>".($g=(grep$f!~$_,a..zz)[0]),$x{$g}=s/@/$g/
while s|\($i\)|$1|g,s|$i[*/]$i|@|||s|$i[+-]$i|@|;$_="$x
\tOUTI $_\tEOJ
";s/>$i<\1//g;s!(^|\b)[-+/*<>]!\n\t$m{$&} 0,!g;
s!-?\d+$!'$&'!mg;print;print"$_\tDS F
"for keys%x

Ejemplo de uso:

$perl winali.pl <<<"2*a-b*c+d"
    INI b
    INI a
    INI d
    INI c

    LDA 0,'2'
    MUL 0,a
    STA 0,a
    LDA 0,b
    MUL 0,c
    STA 0,b
    LDA 0,a
    SUB 0,b
    ADD 0,d
    STA 0,b
    OUTI b
    EOJ
b   DS F
a   DS F
d   DS F
c   DS F
nutki
fuente
Verificado Sería bueno si la entrada se ordena alfabéticamente. Solo un consejo: las líneas vacías se ignoran, por lo que pueden reducir un poco la longitud de salida
GiantTree
Algunas optimizaciones que podría hacer: eliminar la nueva línea final
GiantTree
Con las optimizaciones anteriores, su salida será de 585 bytes (8 bytes menos)
GiantTree
La nueva línea final puede eliminarse sin costo de código, pero eliminar una línea vacía después de INI probablemente costaría más de 4 caracteres de código.
nutki
oh, entonces simplemente elimine la nueva línea final, no es necesaria y le ahorrará 4 bytes :)
GiantTree