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:
-
Sinais de pontuação,
que são representados pelos três seguintes caracteres: ":",
";", ",";
-
Colchetes e parêntesis,
que são representados pelos quatro seguintes caracteres: "[", "]",
"(" e ")";
-
Operadores
lógicos, que são representados pelos quatro seguintes caracteres:
"!", "#", "&" e "|";
-
Operadores
aritméticos, que são representados pelos cinco seguintes
caracteres: "*", "/", "%", "+" e "-";
-
Palavras: O primeiro caracter
de uma palavra é sempre uma letra. Essa primeira letra pode ser
seguida por uma ou mais letras ou algarismos. Os caracteres "$", "'", "^",
"_", "`" e "~" são considerados letras. O número de caracteres
que forma uma palavra foi limitado em 255;
-
Números: O primeiro caracter
de um número é sempre um algarismo. Esse primeiro algarismo
pode ser seguido por um ou mais algarismos ou letras entre "A" e "F". Os
números podem ter uma última letra, que é opcional
e serve para especificar a base na qual foi expresso o valor do número.
Essa última letra pode ser "B", "D", "H" ou "O"", especificando,
respectivamente, as bases 2, 10, 16 e 8. Se essa última letra for
omitida o montador considera que o número está na base 10.
Naturalmente, os algarismos usados para formar o valor do número
devem ser compatíveis com a base especificada. Além disso,
os valores dos números devem ser sempre menores que 216;
-
Cadeias: As cadeias são
sequências caracteres entre aspas. Entre as aspas podem aparecer
qualquer um dos caracteres excluindo apenas os caracteres que indicam final
de linha (que têm códigos "ASCII" 0A, 0C e 0D) ou final de
arquivo (que têm códigos "ASCII" 1A e 1B). Quando for necessário
incluir um caracter aspas em uma cadeia, deve ser usada uma sequência
formada por dois caracteres aspas. Esse esquema é necessário
para evitar que o caracter aspas incluído na cadeia seja confundido
com o caracter aspas que termina a cadeia. O número de caracteres
usados em uma cadeia foi limitado em 255.
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:
-
Definição de rótulo:
Uma definição de rótulo, quando presente em uma linha,
será sempre o primeiro elemento sintático da linha e será
formado por uma palavra seguida pelo sinal de pontuação ":".
A palavra empregada corresponde ao nome do rótulo e não pode
ser igual a nenhum dos nomes dos registradores de 8 bits de uso geral do
processador ("A", "B", "C" ou "D"), nem dos pares de registradores de uso
geral ("AB" ou "CD"), nem "SP", nem "$", nem às palavras empregadas
em definições de rótulos que tenham sido colocadas
em outras linhas do programa, ou seja, cada palavra só pode ser
definido como rótulo uma vez no programa;
-
Instrução: Cada
instrução é formada por um mnemônico de instrução
ou pseudo-instrução que pode ser seguido por um ou mais operandos,
de acordo com o tipo de mnemônico. No caso das instruções
que usarem mais de um operando, deve haver um uma vírgula entre
cada par de operandos consecutivos. Os operandos que podem ser usados dependem
do mnemônico que está sendo empregado e podem ser expressões
numéricas que fornecem valores de operandos imediatos, posições
de memória, nomes de registradores de 8 bits de uso geral ("A",
"B", "C" ou "D"), nomes de pares de registradores ("AB"ou "CD"), "SP" ou
cadeias de caracteres de qualquer tamanho;
-
Comentário: Quando presente
em uma linha será sempre o último elemento sintático
da linha e começará sempre pelo caracter ";". Todo o texto
existente entre o ";" e o final da linha é ignorado pelo montador.
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:
-
expressões numéricas
entre parêntesis;
-
palavras que correspondem a nomes
de rótulos;
-
números;
-
cadeias formadas por um ou dois
caracteres;
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:
-
um operando imediato especificado
através de uma expressão numérica,
que indica uso do modo de endereçamento imediato indireto;
-
os nomes dos pares de registradores
"AB" ou "CD", que indica o uso do modo de endereçamento indireto
implícito;
-
uma expressão aditiva
em que uma e apenas uma das parcelas é um dos pares de registradores
"AB" ou "CD" e as demais parcelas são parcelas
de expressões numéricas. Essa forma indica o uso do modo
de endereçamento indexado. As expressões aditivas devem ser
formadas por duas ou mais parcelas separados pelos operadores aritmético
de soma ("+") ou subtração ("-"), sendo que a parcela correspondente
ao par de registradores deve ser a primeira ou ser prescedida pelo operador
de soma. O montador realiza a soma ou subtração de todas
as parcelas de expressões numéricas que forem especificadas
na expressão aditiva para obter o operando imediato que é
empregado nesse modo de endereçamento.
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:
-
Instruções sem
operandos, com seis mnemônicos: "RET", "CLC", "CMC", "STC", "HALT"
e "NOP";
-
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";
-
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");
-
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";
-
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";
-
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";
-
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;
-
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");
-
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:
-
Se o primeiro operando for um
dos registradores de 8 bits de uso geral, o segundo operando pode ser uma
expressão numérica, qualquer um dos outros registradores
de uso geral de 8 bits ou uma posição de
memória endereçada de qualquer um dos modos admitidos;
-
Se o primeiro operando for uma
posição de memória endereçada
no modo imediato indireto, o segundo operando pode ser um operando
imediato especificado através de uma expressão
numérica, qualquer um dos registradores de 8 bits de uso geral,
qualquer um dos pares de registradores ou o registrador "SP";
-
Se o primeiro operando for uma
posição de de memória endereçada
nos modos indireto implícito ou indexado, o segundo operando
pode ser qualquer um dos registradores de uso geral de 8 bits que não
façam parte do par de registradores referenciado no primeiro operando
ou o par de registradores que não foi referenciado no primeiro operando;
-
Se o primeiro operando for um
par de registradores, o segundo operando pode ser um operando imediato
especificado através de uma expressão
numérica, uma posição de memória
endereçada de qualquer um dos modos admitidos, o par de registradores
que não foi empregado como primeiro operando ou o registrador "SP";
-
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,
uma posição de memória endereçada
no modo imediato indireto ou um dos pares de registradores;
-
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;
-
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;
-
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";
-
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";
-
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";
-
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;
-
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;
-
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.