Problema 2


Notas

A resolver em grupo.

A resolução deste problema deve ser entregue até ao dia 16 de Novembro de 1998.  A resolução deve ser entregue pessoalmente a um dos docentes da cadeira e consta de uma disquete, devidamente identificada, contendo apenas o ficheiro onde se encontra o código (que se deve chamar "prob2.cpp").

A entrega do problema fora do prazo implica a penalização de um valor por cada dia útil de atraso.

O peso de cada questão na avaliação deste problema é indicado entre [] junto às mesmas.


Questão 1

[100% - 20 valores]

Suponha que se pretende simular uma máquina que executa instruções muito simples.  Considere que a máquina usa apenas três registos (que são também variáveis do simulador): A, B e mem.  Estes registos podem guardar valor inteiros.  A máquina pode executar um conjunto limitado de operações.  A operação a executar é dada por uma variável código cujo tipo é definido do seguinte modo:

enum CódigoDeInstrução {
    END, LOAD_A, STORE_A, LOAD_B, STORE_B, ADD, SUB,
    MUL, DIV, ZERO_A, ZERO_B, INCR_A, DECR_A, INCR_B, DECR_B,
    READ, WRITE
};
O significado dos códigos é: Use o programa de simulação da máquina (incompleto) dado em anexo (ver Programa).  A simulação consiste num ciclo onde, em cada iteração, é camada a função CódigoDeInstrução lêInstrução(....) que devolve (como se pode ver) um código de instrução.  A instrução correspondente a esse código é então executada pelo procedimento executaInstrução().  No fim de cada iteração é chamado o procedimento void mostraEstado() para mostrar o valor corrente das variáveis A, B e mem.  A simulação termina quando a instrução lida for END.  O trabalho consiste em definir os procedimentos :
void mostraEstado(int A, int B, int mem);
void executaInstrução(CódigoDeInstrução código, int &A, int &B, int &mem);
O procedimento void executaInstrução() deve executar uma operação diferente sobre os três parâmetros inteiros (registos passados por referência!) para cada valor possível do parâmetro código.

Para testar o simulador completo, experimente escrever num ficheiro de texto chamado "programa.asm" (use "shift-clique" no netscape para guardar) o seguinte conjunto de instruções:

ZERO_A
STORE_A
READ
ADD
LOAD_B
INCR_B
STORE_B
READ
ADD
LOAD_B
INCR_B
STORE_B
READ
ADD
LOAD_B
INCR_B
DIV
STORE_A
LOAD_B
WRITE
END
e em seguida executar o simulador.  Que faz o programa acima?

Atenção: o ficheiro "programa.asm" deve encontrar-se na mesma directoria onde executar o simulador.


Programa

Em vez de passar o programa à mão, clique aqui (use "shift-clique" no netscape para guardar).
#include <iostream>
using namespace std;
enum CodigoDeInstrucao {
    END,
    LOAD_A,
    STORE_A,
    LOAD_B,
    STORE_B,
    ADD,
    SUB,
    MUL,
    DIV,
    ZERO_A,
    ZERO_B,
    INCR_A,
    DECR_A,
    INCR_B,
    DECR_B,
    READ,
    WRITE
};
void mostraEstado(int A, int B, int mem)
{
    // Escreva aqui o seu código C++.
}
void executaInstrucao(CodigoDeInstrucao codigo, int &A, int &B, int &mem)
{
    // Escreva aqui o seu código C++.
}
// A partir daqui não altere nada...
#include <fstream>
#include <map>
#include <string>
typedef map<string, CodigoDeInstrucao> MapaDeMnemonicas;
CodigoDeInstrucao leInstrucao(istream& canalPrograma, 
                              MapaDeMnemonicas& mnemonicas)
{
    string mnemonica;
    if(!(canalPrograma >> mnemonica)) // lê instrução.
        // Se não conseguiu ler, devolve END para terminar execução.
        return END;
    if(mnemonicas.count(mnemonica) == 0)
        cerr << "Erro: '" << mnemonica << "' não é uma instrução conhecida."
             << endl;
    return mnemonicas[mnemonica];
}
void inicializaMnemonicas(MapaDeMnemonicas& mnemonicas)
{
    mnemonicas[string("END")] = END;
    mnemonicas[string("LOAD_A")] = LOAD_A;
    mnemonicas[string("STORE_A")] = STORE_A;
    mnemonicas[string("LOAD_B")] = LOAD_B;
    mnemonicas[string("STORE_B")] = STORE_B;
    mnemonicas[string("ADD")] = ADD;
    mnemonicas[string("SUB")] = SUB;
    mnemonicas[string("MUL")] = MUL;
    mnemonicas[string("DIV")] = DIV;
    mnemonicas[string("ZERO_A")] = ZERO_A;
    mnemonicas[string("ZERO_B")] = ZERO_B;
    mnemonicas[string("INCR_A")] = INCR_A;
    mnemonicas[string("DECR_A")] = DECR_A;
    mnemonicas[string("INCR_B")] = INCR_B;
    mnemonicas[string("DECR_B")] = DECR_B;
    mnemonicas[string("READ")] = READ;
    mnemonicas[string("WRITE")] = WRITE;
}
int main() 
{
    MapaDeMnemonicas mnemonicas;
    ifstream programa("programa.asm");
    inicializaMnemonicas(mnemonicas);
    int A = 0, B = 0, mem = 0;
    CodigoDeInstrucao codigo;
    while((codigo = leInstrucao(programa, mnemonicas)) != END) {
        executaInstrucao(codigo, A, B, mem);
        mostraEstado(A, B, mem);
    }
}