WinAli - CPU virtual para entender a linguagem assembly

8

WinAli é um montador de modelos para Windows. Emula uma CPU real e destina-se a ajudar os alunos a aprender e entender a linguagem Assembly.

Artigo alemão da Wikipedia: http://de.wikipedia.org/wiki/WinAli (não há artigo em inglês no momento)

Caso você queira testar sua saída produzida: Link para o Google Drive (o programa em si é em alemão, mas é fácil de usar, mesmo se você não entender alemão)

Algumas informações sobre o WinAli (dados e sintaxe)

Tipos de dados:

O único tipo de dados no WinAli é um "Inteiro" de 2 bytes de comprimento, que é de fato um Smallint ou curto . Portanto, você não precisa cuidar dos tipos corretos. Isso também é arredondado ao dividir.

Variáveis ​​e constantes:

Variáveis ​​são definidas assim após os comandos:

name DS F
  • nome é obviamente o nome da variável
  • DS é a palavra-chave para uma nova variável
  • F define o comprimento da variável em bits; isso é baseado em zero e hexadecimal, então F = 16 bits

As constantes são muito semelhantes:

name DC value
  • nome é simplesmente o nome da constante
  • DC é a palavra-chave para uma nova constante
  • value é o valor atribuído a essa constante, por exemplotwo DC '2'
  • Você não precisa especificar constantes no final do código. Você também pode escrevê-los em linha com a LDAoperação (carregar), por exemplo LDA 0,'2'. Isso carrega "2" no registro 0 (o acumulador).
Sintaxe:

O código está alinhado em 4 colunas separadas por um espaço ou tabulação:

label command params comment
  • label é usado para o b labelcomando ( goto label) e geralmente é ignorado.
  • comando um dos comandos listados abaixo.
  • modela um ou dois parâmetros com pelo menos um registro e, se necessário, outro registro, variável, pilha ou endereço; esses parâmetros são separados por vírgula ( ,).
  • comentários (opcional) um comentário prefixado com ;ou *até o final da linha.

Referência de código pequeno:

Existem mais comandos, mas para esse desafio você precisa apenas desses:

  • INI A Armazena a próxima entrada do usuário na variável A
  • OUTI AEmite o valor que a variável Aestá mantendo. Você não pode usar um registro aqui por algum motivo.
  • LDA 0,ACarrega o valor de Ano registro 0
  • STA 0,A Armazena o valor do registro 0 na variável A
  • ADD 0,AAdiciona o valor de Aao valor do registro 0
  • SUB 0,AMultiplica o valor de Acom o valor do registro 0
  • DIV 0,ADivide o valor de Apelo valor do registro 0
  • EOJDefine o final do trabalho, ou seja, código executável. Declarações variáveis ​​e constantes começam após esta marca.

Não é explicitamente necessário para este desafio:

  • program START 0Define o primeiro endereço a ser executado como 0, ou seja, a próxima linha ( programé apenas o nome do programa, mas é necessário para o compilador)
  • END program Finaliza o programa, ou seja, para de executar, mesmo que outras operações sigam

O seu desafio!

Escreva um programa ou script que obtenha uma expressão matemática com números e variáveis ​​constantes e produz o código WinAli que utiliza todas as variáveis ​​como entrada e gera o resultado dessa expressão.

  • Você não precisa emitir os comandos STARTeEND
  • Embora existam 16 registros definidos no WinAli, usamos apenas o registro 0, que é o acumulador para todos os cálculos
  • Você não pode usar duas variáveis ​​como parâmetros de um comando. Você precisa salvar todos os seus resultados no acumulador (registro 0)
  • A entrada está sempre na forma de um x:=(a+b)/cou simplesmente (a+b)/c, você decide
  • Você só precisa cuidar + - * / (ADD, SUB, MUL, DIV), portanto, não há cálculos complexos como raízes, quadrados ou até mesmo sinusite
  • Dica: Tente primeiro extrair expressões simples com apenas 2 argumentos, por exemplo a:=a+b,x:=a/c
  • Dica: Seu programa poderá usar variáveis ​​adicionais (auxiliares) se você não puder sobrescrever variáveis ​​que não serão usadas posteriormente no seu código. Defina-os como h1 DS F.
  • Dica: Linhas vazias são inúteis. Tente evitá-los. (Você realmente não precisa deles)

Exemplo:

Expressão matemática:
 x: = (a + b) * c

Saída esperada (linhas vazias são para facilitar a leitura):
    INI a
    INI b
    INI c

    LDA 0, um
    ADICIONAR 0, b
    MUL 0, c
    STA 0, a

    OUTI a
    EOJ
um DS F
b DS F
c DS F

Pontuação:

Sua pontuação é definida pelo comprimento do seu código + o comprimento da saída das seguintes expressões:

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

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

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

x:=2*a-b*c+d
  • -10% se o seu código puder lidar com menos unário em expressões.

Em caso de empate, a resposta que produz o menor código WinAli em funcionamento vence.

As soluções não podem ser codificadas de forma alguma. Validarei cada resposta com expressões adicionais para garantir que sua resposta esteja correta.

GiantTree
fonte
O que exatamente é uma expressão matemática? Por exemplo, constantes negativas são permitidas? Unário menos? Nomes de variáveis ​​com mais de uma letra?
nutki
As diretivas de entrada (INI x) precisam seguir alguma ordem específica?
nutki
@nutki uma expressão matemática é entendida como um simples x = a + b, portanto, não é possível resolver equações complexas, constantes negativas, nomes de variáveis ​​podem ter mais de uma letra (ab não é a * b), INI x pode ser colocado onde sempre que você como não há nenhuma ordem específica necessária, uma vez que armazena a próxima entrada na variável dar, mas seria bom se eles seguirem o az fim em vez de ser aleatória
GiantTree
@nutki por menos unário você quer dizer coisas como MUL 0,-a? isso não é possível porque não há endereços negativos ( aé apenas um ponteiro para um valor), mas você pode subtrair o valor de 0 para obter a representação negativa ( SUB 0,a) e trabalhar com esse valor negativo; você pode até armazenar isso na variável original.
GiantTree
Eu quis dizer menos unário na expressão de entrada, por exemplo, x:=-a*bou x:=a/-(b+c). Como a ordem de entrada não está especificada, acho que precisamos usar os mesmos nomes de variáveis ​​no código WinAli, é esse o caso? Com essas restrições, existem identificadores que nunca estão na entrada? Por exemplo, pode h1ser um nome de variável de entrada?
nutki

Respostas:

4

Perl 5: 948, código 355 + saída 593

Depois de jogar golfe. A versão mais curta anterior não foi analisada corretamente (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

Exemplo 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
fonte
Verificado. Seria bom se a entrada for classificada em ordem alfabética. Apenas uma dica: vazio linhas são ignoradas para que eles possam reduzir o seu comprimento de saída um pouco
GiantTree
Algumas otimizações que você poderia fazer: remover a nova linha de fuga
GiantTree
Com as otimizações acima de sua saída será 585 bytes de comprimento (8 bytes menos)
GiantTree
A nova linha à direita pode ser removida sem nenhum custo de código, mas remover uma linha vazia após o INI provavelmente custaria mais de 4 caracteres de código.
nutki
oh, em seguida, basta remover o final de linha, não é necessário e você vai economizar 4 bytes :)
GiantTree