Ir para o conteúdo principal
Paca
  • Página inicial
  • Mais
Você acessou como visitante
Acessar
Página inicial
  1. Semestres anteriores
  2. MAC0323 2018
  3. PR05
Tarefa

PR05

Condições de conclusão
Aberto: quinta-feira, 7 jun. 2018, 00:00
Vencimento: sábado, 7 jul. 2018, 23:55

Parte V: Montador e Vinculador

Na última parte do nosso projeto você vai terminar de implementar o montador (ou seja, sua própria versão do MACAs) e também o vinculador (sua própria versão do MACLK).

Montador

Usando o parser da parte IV, você deve implementar a função cujo protótipo está em asm.h que é a parte principal do montador. Esse arquivo pode ser copiado daqui.

O arquivo asm.h contém apenas o protótipo da função que vocês devem implementar:

int assemble(const char *filename, FILE *input, FILE *output);

O protótipo dessa função não deve ser alterado.

A função assemble() recebe:

  • o nome filename do arquivo de entrada. Esse nome será útil para imprimir mensagens de erro. Por exemplo a seguir bla.c é o filename: sh % gcc bla.c gcc: error: bla.c: No such file or directory gcc: fatal error: no input files compilation terminated.

  • um stream input de entrada que é um ponteiro para o arquivo com programa em MACAL a ser montado.

  • um strem output de saída que é um ponteiro para o arquivo que será criado com o código-objeto.

A função assemble() deve imprimir mensagens de erro apropriadas em stderr, da mesma forma que o montador disponibilizado no PACA. Caso a montagem seja feita com sucesso, a função deve devolver um valor não-zero; caso contrário devolve zero.

Você também deve escrever um arquivo macas.c que contém a função main() do montador. Essa função apenas interpreta os argumentos recebido através da linha do comando, abre os arquivos de entrada e saída e chama a função assemble() para fazer a montagem. A função main() também deve gerar mensagens de erro apropriadas caso detecte alguma falha.

Erros seu programa deve detectar

Erros relacionados a operandos inválidos para uma operação, por exemplo, são capturados pela função parse() do parser.c. Seu trabalho então é apenas reportar esses erros e encerrar a execução. Além desses erros, o montador deve capturar os seguintes erros:

  • um rótulo de uma instrução não pode ser um alias e vice-versa;

  • aliases não podem ser definidos mais de uma vez;

  • uma instrução EXTERN não pode ter um rótulo; o rótulo exportado pela EXTERN deve ser definido;

  • rótulos não podem ser definidos mais de uma vez;

  • as instruções de desvio tais com JMP e JZ suportam deslocamentos de tamanho máximo fixo; veja o capítulo 7 da apostila sobre MACAL disponível no PACA. Seu programa deve verificar se esses tamanhos foram respeitados.

O código-objeto

Você deve gerar um arquivo com o código-objeto do programa. O formato desse arquivo não está especificado: você deve inventar um formato próprio que facilite sua vida na hora de escrever o vinculador.

Tipicamente, a maior parte das instruções do programa original devem ser convertidas imediatamente em instruções de máquina. A conversão não é possível apenas quando temos uma instrução de desvio, como JMP, para um rótulo não definido até o momento. Nesse caso, o seu programa deve marcar no código-objeto esse deslocamento para o rótulo desconhecido. Outra informação importante que o seu programa deve registrar no código objeto é a posição de cada rótulo que foi exportado, para que o vinculador determine as posições das instruções correspondentes ao montar o programa final.

O vinculador (linker) será o programa responsável por encontrar os rótulos desconhecidos no código-objeto, calcular os deslocamentos e completar o código de máquina a ser executado pelo macsim.

Sugestão

Aqui vai uma sugestão de como estruturar a função assemble(). Você está livre para fazer a implementação do maneira que considerar mais conveniente.

Considere manter três tabelas de símbolos (stable):

  • alias_table: guarda os alias definidos através de IS;

  • label_tabel: guarda os rótulos definidos e o número da instrução a que correspondem;

  • extern_tabel: guarda os rótulos definidos como EXTERN.

A alias_table deve conter inicialmente alguns aliases padrão, a saber os registradores com nomes especiais: rA rX, etc.

Você pode dividir a montagem em duas etapas.

Na primeira etapa, seu programa deve ler cada instrução do arquivo de entrada (input) e montar uma lista de instruções. Esse lista será uma lista ligada de instâncias do tipo Instruction. Durante esta primeira etapa, o seu programa deve atualizar quando preciso as tabelas de símbolo acima, mas não deve gerar código máquina algum.

Note que seu programa não deve inserir instruções que não geram código, tais como EXTERN ou IS, na lista ligada de instruções. Seu programa deve manter um contador com a posição da próxima instrução no código-objeto. No momento em que uma instrução é inserida na lista, você conhece sua posição no arquivo e pode mudar o campo pos da instrução apropriadamente. Em seguida, basta atualizar o contador com a posição da próxima instrução. Pseudo-operações como CALL ou PUSH geram mais de uma instrução de máquina. Quando uma instrução com rótulo é lida, sabemos a posição à qual o rótulo se refere e podemos atualizar a tabela label_table para guardá-la.

Na segunda etapa, seu programa deve percorrer a lista de instruções e gerar o código-objeto. A medida que percorre a lista, o código de cada instrução é gerado. Se há uma instrução de desvio, como JMP, devemos verificar se o rótulo do desvio foi definido em label_table e nesse caso calcular o deslocamento. Se o rótulo não foi definido, a instrução deve ser apenas parcialmente gerada código-objeto. O vinculador resolverá essa dependência mais tarde.

Vinculador

O vinculador é mais simples de escrever do que o montador. Ele pode ser composto de apenas um arquivo maclk.c. Seu trabalho consiste em ler diversos arquivos com código-objeto maco e montar o programa final em código de máquina mac. O vinculador deve verificar se os rótulos não-resolvidos de cada arquivo foram exportados com EXTERN por um outro arquivo a fim de calcular os deslocamentos finais. O vinculador também deve certificar-se de que o rótulo main foi exportado por algum arquivo, para determinar a instrução inicial do programa mac.

O vinculador detecta três tipos de erro:

  • rótulo main não definido;
  • um mesmo rótulo definido mais de uma vez;
  • algum rótulo não definido.
Você acessou como visitante (Acessar)
Resumo de retenção de dados
Baixar o aplicativo móvel.
Fornecido por Moodle