Lab 14: Vm Translator
O VMTranslator é um programa escrito em Java que faz a tradução de códigos escrito na linguagem VM definida no curso e traduz para linguagem Assembly do computador Z01.
Testando
Para testar, primeiramente executar o comando:
$ ./genJAR.py
que irá criar o executável em Java.
Na sequência, executar:
$ ./compileALL.py
que irá converter todos os arquivos em VM para linguagem de máquina usando dois tradutores: um já fornecido e o criado por vocês.
Por fim, executar:
$ ./pytest --tb=no -s
que irá testar as saídas esperadas.
O diagrama da testagem seria:
             genJAR.py
                 |   
                 |   
                 V
            VMTranslator          Assembler            Z01-Simulator  ------------------
 arquivo.vm -------------> .nasm -----------> .hack  > ------------>  - Verifica saída -
                                                                      ------------------
Para auxiliar, foram criados alguns programas (h_VM/src/Examples/) em VM muito específicos que testam somente um comando, ou uma parte da tradução do VMTranslator. Por exemplo o teste SimpleAdd possui somente a seguinte linha:
add
Esse teste foi criado para testar o Code.writeArithmetic no caso de um comando add. Para isso, antes da execução desse código, o simulador faz a inicialização da RAM, simulando valores na pilha e já configurando o SP para uma situação real. A memória antes da execução da instrução add é a seguinte:
    0 : 0000000100000010;
  256 : 0000000000000010;
  257 : 0000000000000100;
  258 : 0000000000000000;
Note
h_VM/tests/tst/SimpleAdd/SimpleAdd0_in.mif
Espera-se o resultado final após a execução do comando add :
    0 : 0000000100000001
  256 : 0000000000000110
A seguir uma lista de como cada parte do VMTranslator é testado:
code.writePushPop- pop
- SimplePopTemp : pop temp ...
 - SimplePopLocal : pop local ...
 - SimplePopThat : pop that ...
 - SimplePopThis : pop this ...
 
 - push
- SimplePushConst : push constant ....
 - SimplePushTemp : push tempo ....
 - SimplePushLocal : push local ....
 - SimplePushArg : push argument ...
 - SimplePushThis : push this ...
 - SimplePushThat : push that ...
 
 
- pop
 - code.writeArithmetic
- SimpleAdd : add
 - SimpleNeg : neg
 - SimpleSub : sub
 - SimpleEq : eq
 - SimpleGt : gt
 - SimpleLt : lt
 - SimpleAnd : and
 - SimpleOr : or
 
 
Implementando
Vamos agora fazer a implementação do comando push constant 3 no VMtranslator.
- Abra o projeto da mesma maneira que realizado no 
Assembler- o arquivo maven está na pasta 
h_VMTranslator/VMtranslator 
 - o arquivo maven está na pasta 
 
Nesse projeto vocês terão que mexer apenas no Code.java, os demais módulos já estão prontos (similar ao projeto do Assembler, temos nesse o parser, VMTranslator, ...).
Editando o Code.java
No Code.java encontre a implementação do método push , linha 121
public void writePushPop(Parser.CommandType command, String segment, Integer index) {
...
...
...
 else if (command == Parser.CommandType.C_PUSH) {
            commands.add(String.format("; %d - PUSH %s %d", lineCode++ ,segment, index));
            if (segment.equals("constant")) {
            }
Essa método é chamado sempre que um comando push/pop for interpretado, exemplo:
push constant 3
Os parâmetros recebidos são:
- command: 
C_PUSH - segment: 
constant - Index: 
3 
Precisamos agora traduzir a execução desse comando em vm para nasm para que ele possa ser executado no nosso hardawre, isso é pode ser feito seguindos os passos a seguir:
- Carregar o valor da constante em um registrador disponível
 - Busca no StackPointer(SP) o endereço da posição vazia da stack
 - Mover o valor do Index (no caso 3) para essa posição vazia
 - Incrementa SP em um
 
Implementando
Faça a tradução do comando push constant nnn de VM para nasm, 
para cada linha nasm você deve chamar a função commands.add, como no exemplo 
a seguir:
commands.add("movw %A, %D");
A tradução deve ser escrita dentro do if (segment.equals("constant")) {....}
Solução
// carrega a constant em %A e move para %D
commands.add("leaw $"+ index + ", %A");
commands.add("movw %A, %D");
// carrega o calor do SP e move a constant
// para o topo da pilha
commands.add("leaw $0,%A");
commands.add("movw (%A),%A");
commands.add("movw %D,(%A)");
// altera stack pointer: SP = SP + 1
commands.add("leaw $0,%A");
commands.add("movw (%A),%D");
commands.add("incw %D");
commands.add("movw %D, (%A)");
Para testar o projeto VMtranslator, não há testes unitários disponíveis. No caso do push constant, temos o teste SimplePushConst, bastando apenas habilitar este teste na config (config_testes_vm.txt). Se observar o arquivo, irá perceber que existem diversos outros testes básicos, como SimplePushLocal, SimplePopLocal e outros que podem ser habilitados conforme estes recursos forem implementados no seu VMtranslator.