8. O PROGRAMA MONTADOR PARA A MÁQUINA 2002

O programa montador para a máquina 2002 pode ser obtido aqui. Esse foi codificado em PASCAL e compilado utilizando o "TURBO PASCAL" versão 7.0. O código fonte desse programa pode ser obtido aqui.

Esse programa implementa um montador de dois passos que lê o texto que corresponde ao programa em linguagem de montagem de um arquivo cujo nome pode ser especificado como parâmetro na linha de comando que invoca a execução do montador. Se não for especificado um nome de arquivo na linha de comando, o montador vai pedir o nome desse arquivo através de uma pergunta específica. O arquivo que armazena o texto do programa em linguagem de montagem deve ter um tamanho menor que 216 bytes (64Kilobytes). O texto desse programa deve ter sido construído respeitando as regras léxicas, sintáticas e semânticas da linguagem tratada pelo montador.

No primeiro passo, o montador cria uma tabela que conterá todos os rótulos que vierem a ser definidos no programa que está sendo montado. Nessa tabela, cada um dos rótulos será associado ao respectivo valor.

Durante o segundo passo, o montador constrói o programa em linguagem de máquina e gera um texto de saída que será apresentado na tela. É possível armazenar esse texto em um arquivo utilizando a opção de redirecionamento de saída na linha de comando que invoca o montador. Cada linha do programa em linguagem de montagem geralmente provoca a geração de uma linha nesse texto de saída do montador.

Essa linha conterá o endereço e o código gerado pelo montador como tradução da linha do programa em linguagem de montagem correspondente, seguido pelo número da linha e da própria linha lida do programa em linguagem de montagem. Linhas suplementares serão geradas em dois casos: Se o código gerado pelo montador para a linha do programa em linguagem de montagem ocupar mais de quatro bytes ou se tiverem sido encontados erros durante a montagem dessa linha. No primeiro caso, as linhas suplementares conterão a continuação do código gerado pelo montador enquanto que no segundo caso a linha suplementar conterá uma mensagem de erro apropriada.

Ao final do segundo passo, o montador apresenta uma mensagem que informa o número de erros encontrados e lista todos os rótulos que tiverem sido definidos no programa montado, juntamente com os valores associados a cada um desses rótulos e a seguir pede o nome de um arquivo onde deve ser colocado o código gerado. Nesse arquivo será colocado o código gerado através da montagem do programa sob a forma de um texto em um formato compatível com o formato aceito pelo programa carregador.


8.1. ASPECTOS LÉXICOS DA LINGUAGEM DE MONTAGEM

Os programas em linguagem de montagem são textos nos quais as letras minúsculas são consideradas como equivalentes às letras maiúsculas correspondentes. Esses textos são formados por linhas que podem conter os sete seguintes tipos de elementos léxicos:

As cadeias formadas por um ou dois caracteres são consideradas como equivalentes a números. Se a cadeia for composta por apenas um caracter, o valor do número equivalente a essa cadeia será o código "ASCII" do único caracter da cadeia. Se a cadeia for composta por dois caracteres, o valor do número equivalente a essa cadeia será formado por 16 bits, sendo que os 8 bits menos significativos conterão um valor igual ao código "ASCII" do primeiro caracter da cadeia e os 8 bits mais significativos conterão um valor igual ao código "ASCII" do segundo caracter da cadeia.

Nas situações nas quais uma palavra é imediatamente seguida por outra palavra ou por um número, deve haver pelo menos um espaço em branco ou caracter de tabulação separando a palavra do elemento léxico subsequente. Em todas as demais situações, espaços em branco ou caracteres de tabulação que vierem a ser colocados antes ou depois de elementos léxicos são totalmente ignorados pelo programa montador.



8.2. ASPECTOS SINTÁTICOS DA LINGUAGEM DE MONTAGEM

As linhas do texto que corresponde ao programa em linguagem de montagem devem ser formadas por três tipos de elementos sintáticos, que são todos opcionais, mas que, caso presentes, devem aparecer nessa ordem:

As expressões numéricas são formadas por um ou mais termos de expressões numéricas separados por operadores lógicos diferentes de "!". Os operadores lógicos diferentes de "!" são "#", "&" e "|" e servem para especificar, respectivamente, a realização das operações lógicas "ou exclusivo", "e" e "ou" sobre os valores dos termos de expressões entre os quais forem colocados.

Os termos de expressões numéricas são formados por uma ou mais parcelas de expressões numéricas separadas pelos operadores aritméticos "+" ou "-". O operador aritmético "+" especifica que as parcelas entre os quais ele aparece devem ser somadas enquanto que o operador aritmético "-" especifica que a relização de uma subtração onde o minuendo é o valor da parcela imediatamene anterior a esse operador e o subtraendo é  o valor da parcela imediatamente seguinte a esse operador.

As parcelas de expressões numéricas são formadas por um ou mais fatores separados pelos operadores aritméticos "*", "/" ou "%" que indicam, respectivamente, a realização das operações aritméticas de multiplicação, divisão, e resto da divisão entre os fatores entre os quais forem colocados.

Os fatores são valores numéricos opcionalmente prescedidos pelo operador lógico "!" ou pelo operador aritmético "-". O operador lógico "!" especifica que o valor numérico seguinte deve ser negado bit a bit enquanto que o operador aritmético "-" especifica que o valor numérico seguinte deve sofrer uma operação de complemento a dois.

Os valores numéricos podem ser:

As posições de memória são formadas por endereços entre colchetes. A forma assumida por esses endereços indica o modo de endereçamento que será empregado pela instrução e pode ser:

8.3. ASPECTOS SEMÂNTICOS DA LINGUAGEM DE MONTAGEM

Os tipos de operandos admitidos por cada um dos mnemônicos de instruções ou pseudo-instruções utilizados são restritos às combinações admitidas pelo conjunto de instruções suportado pelo processador da Máquina 2002. Assim, para efeito de determinação dos tipos de operandos são admissíveis por cada um dos 59 mnenônicos das instruções e pseudo-istruções empregados, esses mnemônicos são divididos nas seguintes 17 categorias:

  1. Instruções sem operandos, com seis mnemônicos: "RET", "CLC", "CMC", "STC", "HALT" e "NOP";
  2. Instruções de Entrada e Saída, dois mnemônicos: "IN" e "OUT". Empregam apenas um operando que pode ser o registrador "A" ou o registrador "B";
  3. Instruções de pilha, com dois mnemônicos: "PUSH" e "POP". Empregam apenas um operando que pode ser: qualquer um dos registradores de 8 bits de uso geral ("A", "B", "C" ou "D"), o registrador de indicadores ("F"), uma posição de memória endereçada no modo imdediato indireto, um dos pares de registradore de uso geral ("AB" ou "CD");
  4. Instruções de incrementação e decrementação, com dois mnemônicos: "DEC" e "INC". Empregam um único operando que pode ser qualquer um dos registradores de 8 bits de uso geral ("A", "B", "C" ou "D"), uma posição de memória endereçada no modo imediato indireto, qualquer um dos pares de registradores ("AB" ou "CD") ou o registrador "SP";
  5. Instruções aritméticas e lógicas unárias, com seis mnemônicos: "NOT", "NEG", "SHL", "SHR", "RL" e "RR". Empregam apenas um operando, que pode ser o registrador "A", o registrador "B" ou o par de registradores "AB";
  6. Instruções de desvio incondicional relativo, com apenas um mnemônico: "JR". Empregam um único operando que pode ser um operando imediato especificado através de uma expressão numérica, o registrador "A" ou o registrador "B";
  7. Instruções de desvio condicional dependentes de indicadores, com 16 mnemônicos: "JS", "JP", "JO", "JC", "JZ", "JZC", "JSO", "JSONZ", "JNS", "JNP", "JNO", "JNC", "JNZ", "JNZC", "JNSO", "JZNSO". Empregam um único operando que só pode ser um operando imediato especificado através de uma expressão numérica;
  8. Instruções de desvio absoluto e chamadas de subrotinas, com dois mnemônicos: "JMP" e "CALL". Empregam um único operando que pode ser um operando imediato especificado através de uma uma expressão numérica ou um dos pares de registradores ("AB" ou "CD");
  9. Instruções de movimentação de dados, com apenas um mnemônico: "MOV". Empregam dois operandos, sendo que o primeiro operando pode ser qualquer um dos registradores de 8 bits de uso geral ("A", "B", "C" ou "D"), ou uma posição de memória endereçada de qualquer um dos modos admitidos, ou qualquer um dos pares de registradores ("AB" ou "CD"), ou o registrador "SP". Os tipos de segundo operando admitidos dependem do tipo do primeiro operando:
  10. Instruções de subtração e adição, com dois mnemônicos "SUB" e "ADD". Empregam dois operandos, sendo que o primeiro operando pode ser o registrador "A", o registror "B", um dos pares de registradores ou o registrador "SP". Se o primeiro operando for o registrador "A" ou o registrador "B", o segundo operando poe ser um operando imediato especificado através de uma expressão numérica ou qualquer um dos quatro registradores de 8 bits de uso geral que seja diferente do registrador especificado como primeiro operando. Se o primeiro operando for um par de registradores, o segundo operando pode ser um operabdo imediato especificado através de uma expressão numérica ou o outro par de registradores. Se o primeiro operando for o registrador "SP", o segundo operando pode ser um operando imediato especificado através de uma expressão numérica ou um dos pares de registradores;
  11. Instruções aritméticas e lógicas binárias, com seis mnemônicos: "SBB", ÄDC", "CMP", "AND", "XOR" e "OR". Empregam dois operandos, sendo que o primeiro pode ser o registrador "A" ou o registrador "B" enquanto que o segundo pode ser um operando imediato especificado através de uma expressão numérica ou qualquer um dos quatro registradores de 8 bits de uso geral que seja diferente do registrador especificado como primeiro operando;
  12. Instruções de multiplicação, com dois mnemônicos: "MUL" e "IMUL". Empregam dois operandos, sendo que o primeiro é sempre o registrador "A" e o segundo é sempre o registrador "D";
  13. Instruções de divisão, com dois mnemônicos: "DIV" e "IDIV". Empregam dois operandos, sendo que o primeiro é sempre o par "AB"e o segundo é sempre o registrador "D";
  14. Instruções de expansão com preservação de sinal, com apenas um mnemônico: "EXP". Emprega dois operandos, sendo que o primeiro é sempre o registrador "A"e o segundo é sempre o registrador "B";
  15. Instruções de desvio condicional dependentes de valores de registradores, com três mnemônicos: "JEQZ", "JNEQZ", "LOOP". Empregam dois operandos, sendo que o primeiro é um dos registradores de 8 bits de uso geral e o segundo é sempre um operando imediato especificado através de uma expressão númerica;
  16. Pseudo-Instruções de alocação de memória, com dois mnemônicos: "DB" e "DW". Empregam um ou mais operandos, sendo que cada um dos operandos pode ser uma expressão numérica ou cadeias de qualquer tamanho;
  17. Pseudo-Instruções críticas, com três mnemônicos: "EQU", "ORG" e "RES". Empregam apenas um operando que deve ser uma expressão numérica. Todos os rótulos que venham a ser empregados nessa expressão numérica devem ter sido definidos em linhas anteriores. No caso da pseudo-instrução "EQU", a linha deve ter sido obrigatoriamente iniciada pela definição de um rótulo, que vai ser associado ao valor da expressão numérica que for empregada como operando.