7.1. ASPECTOS GERAIS
7.2. O FORMATO DOS DADOS FORNECIDOS AO CARREGADOR
7.3. CARREGANDO PROGRAMAS ARMAZENADOS EM "FITA DE PAPEL"
7.4. O CÓDIGO DO PROGRAMA CARREGADOR
O programa carregador para a máquina 2002 fica armanenado nos endereços iniciais da "ROM" da máquina 2002. Dessa forma, ele está sempre disponível para execução. O carregador permite preencher a memória da máquina 2002 com valores que devem ser fornecidos em hexadecimal em um formato bastante simples. Como esses valores hexadecimais podem corresponder ao código das instruções que compõem um programa, o carregador implementa uma forma bem simples de colocar um programa na memória da máquina 2002.
A primeira instrução do programa carregador fica armazenada na primeira posição da "ROM", cujo endereço é 0000. Dessa forma, para executar o carregador basta zerar o registrador IP (o que pode ser obtido acionando a tecla "PgUp") e a seguir disparar o processador (através do acionamento da tecla "PgDn"). A execução do programa carregador começa com a apresentação no teletipo de uma linha com uma mensagem na qual o carregador se identifica. No início da linha seguinte, o carregador apresenta o caracter ">". Esse caracter indica que o carregador está pronto para receber os dados.
7.2. O FORMATO DOS DADOS FORNECIDOS AO CARREGADOR
Os dados devem ser fornecidos ao programa carregador como um texto formado por linhas iniciadas pelo endereço da primeira posição de memória a ser preenchida, que deve ser fornecido como um número formado por até quatro algarismos hexadecimais, seguido pelo caracter ":" e pelos valores que devem ser colocados nas posições de memória a partir do endereço especificado, que devem ser fornecidos como números formados por até dois algarismos hexadecimais. Após a cada um desses valores deve haver um ou mais espaços em branco. Tanto os endereços como os valores a serem colocados na memória podem ser fornecidos como números negativos. Os números negativos devem ser fornecidos utilizando a notação usual, ou seja, colocando o sinal "-" antes do valor absoluto do número.
O carregador considera a linha como terminada ao receber qualquer caracter que não corresponda a um algarismo hexadecimal e não seja o espaço em branco nem o caracter "-". Se o caracter que termina a linha for asterisco, o carregador considera que existe um comentário a seguir a esse asterisco. Para ignorar esse comentário, o carregador descarta todos os caracteres recebidos após o asterisco. O final do comentário é indicado pela presença do caracter de "retorno de carro", que é associado à tecla <ENTER>. Após o final de cada linha o carregador apresenta o caracter ">" no início da linha seguinte, para indicar que está pronto para receber um linha subsequente.
Imediatamente antes do caracter ":" que separa o endereço dos valores e imediatamente após a esse caracter podem ser colocados um ou mais espaços em branco, que serão ignorados pelo carregador. Os algarismos hexadecimais que correspondem às letras de "A" a "F" podem ser fornecidos empregando letras minúsculas ou maiúsculas.
O carregador armazena o primeiro valor fornecido em uma linha na posição de memória especificada pelo endereço informado no início da linha e os demais valores seguintes nas posições de memória cujos endereços são imediatamente subsequentes. Dessa forma, a linha ">457A:25 97 AB 4A X" causaria o prenchimento das posiçoes de memória cujos endereços em hexadecimal são 457A, 457B, 457C e 457D com os valores hexadecimais 25, 97, AB e 4A, respectivamente. Observe que essa linha foi terminada pela letra "X". Na realidade, qualquer outro caracter que não fosse um espaço em branco, nem asterisco, nem correspondesse a um algarismo hexadecimal, poderia ter sido empregado.
O carregador não permite o uso das teclas de edição, ou seja, não é possivel corrigir eventuais erros de digitação. Isso acontece porque os valores fornecidos vão sendo colocados nas respectivas posições de memória a medida que são recebidos pelo carregador. Na realidade, cada valor é colocado na sua posição de memória quando o montador recebe o premeiro espaço em branco seguinte a esse valor.
Existe, porém, um recurso limitado para correção de erros: apenas os dois últimos algarismos hexadecimais de cada valor são efetivamente levados em conta pelo carregador. Dessa forma, um valor digitado incorretamente pode ser corrigido digitando o valor correto imediatamente a seguir ao incorreto. Por exemplo: O valor correto é 3A mas foi sido digitado 9A. Essa ituação poderia ser corrigida digitando o valor 3A logo após ao valor incorreto o que forneceria ao montador o número 9A3A. Como o carregador só leva em consideração os dois últimos algarismos, o valor que efetivamente seria colocado na memória seria realmente 3A.
Um esquema semelhante para correção de erros pode ser empregado caso o endereço tenha sido digitado incorretamente. A única diferença é que nesse caso o carregador vai considerar os últimos quatro algarismos hexadecimais digitados para obter o valor do endereço. Naturalmente, como o endereço é o primeiro elemento da linha, um erro na digitação do endereço também pode ser corrigido terminando a linha imediatamente após o erro e começando um nova linha com o endereço correto. Para terminar a linha antes de terminar o fornecimento do endereço basta empregar um caracter que não seja nem espaço em branco, nem asterisco, nem dois pontos e não corresponda a um algarismo hexadecimal.
Para terminar a execução do programa carregador pode-se simplesmente parar o processador da máquina 2002, acionando o botão de parada que é associado à tecla "Home" ou terminar uma linha utilizando a letra "T" maiúscula ou minúscula. A vantagem de terminar empregando a letra "T" é que nesse caso o programa carregador vai parar de uma tal forma que o registrador IP vai receber um valor igual ao endereço da primeira posição do espaço de endereçamento ocupado por memória do tipo "RAM" (endreço 1000H). Assim, se nessa primeira posição de "RAM" tiver sido colocada a primeira instrução do programa que foi carregado, ou uma instrução de desvio para essa primeira instrução, torna-se possível começar a execução do programa que foi carregado sem ter que explicitamente colocar no registrador IP o endereço da posição de memória em que está a primeira instrução desse programa. Nesse caso, a execução do programa que foi carregado poderia ser iniciada simplesmente acionando o botão que dispara o processador, que é associado à tecla "PgDn".
Como o dispositivo de entrada e saída empregado pela máquina 2002 é um teletipo que dispõe de uma unidade leitora e perfuradora de fita de papel, é possível empregar o programa carregador para colocar na memória um programa que tenha sido previamente gravado em uma "fita de papel". Naturalmente, o conteúdo colocado na "fita de papel" deve estar em um formato compatível com o formato aceito pelo programa carregador, que foi descrito acima. Ou seja, cada linha do texto contido na fita de papel deve começar por um endereço em hexadecimal, seguido pelo caracter ":" e pela lista dos valores a serem colocados na memória, também em hexadecimal, sendo que cada um desses valores deve ser seguido por um ou mais espaços em branco. Ao final de cada linha pode haver um comentário, que deve começar pelo caracter asterisco e terminar pelo caracter de fim de linha, que é o retorno de carro.
Como o simulador da máquina 2002 simula as fitas de papel através de arquivos da máquina hospedeira, torna-se possível carregar progrmas que estejam armazenados em qualquer arquivo da máquina hospedeira construído segundo as regras enunciadas acima. Esses arquivos podem ser produzidos empregando um editor de texto qualquer (por exemplo: "EDIT" do "DOS" ou "Notepad" do "Windows") ou por um outro programa qualquer. É importante ressaltar que em todos os arquivos que armzenem um texto cada linha do texto sempre acaba por pelo menos um caracter de fim de linha, tornando desnecessária qualquer preocupação com a inserção explícita de caracteres de fim de linha.
7.4 O CÓDIGO DO PROGRAMA CARREGADOR
Na Figura 1 é apresentado o código do programa carregador. Para efeito de ilustração, esse código é apresentado em um formato compatível com o utilizado como entrada pelo programa carregador. Naturalmente não faz sentido carregar o programa carregador utilizando o próprio programa carregador e na realidade isso seria impossível, porque o programa carregador fica na região da memória da máquina 2002 que é ocupada por "ROM". Desse forma, essse formato foi empregado apenas para apresentar um exemplo de como um programa poderia ser fornecido ao carregador.
Assim, cada uma das linhas do código do programa carregador corresponte geralmente a uma instrução que é apresentada no seguinte formato: Endereço hexadecimal da posição de memória que armazena o primeiro byte do código da instrução seguido pelo caracter ":" e pela lista dos valores dos bytes correspondentes à instrução, também em hexadecimal, separados entre si por espaços em branco e segidos por um asterisco. Após ao asterisco aparece o número da linha, um outro asterisco e a instrução correspondente em linguagem de montagem.
É importante observar que todo o texto que aparece em cada linha após ao primeiro asterisco seria ignorado pelo carregador porque seria considerado comentário. Esse esquema permite que o código de máquina seja apresentado junto com o código em linguagem de montagem em um formato que é perfeitamente aceitável pelo programa carregador.
Examinando o código do programa carregador pode-se constatar que esse programa emprega duas rotinas: "Escreve" e "LeNum". A rotina "Escreve" começa na posição de memória cujo endereço hexadecimal é 0062 e permite escrever uma cadeia de caracteres que está armazenada na memória a partir do endereço que é passado como parâmetro através do par de registradores "CD". O final da cadeia a ser escrita é indicado por um caracter com código ASCII zero. A rotina "LeNum" começa na posição de memória cujo endereço hexadecimal é 006B e é capaz de ler um número com sinal formado por dezesseis bits em uma base qualquer. Essa rotina recebe a base em que o número deve ser lido como parâmetro através do registrador "B" e retorna o número lido no par de registradores "CD". Além disso, ela também retorna no registrador "A" o código "ASCII" do caracter que foi lido imediatamente após o número e mantém o valor da base na qual foi lido o número no registrador "B".
Embora essas duas rotinas tenham sido escritas especificamente para serem empregadas pelo programa carregador, nada impede que elas venham a ser efetivamente utilizadas por outros programas, uma vez que elas estão permanentemente disponíveis porque estão armazenadas em uma memória "ROM".
Figura 1. Código do programa carregador.
000D * 1 *CR: equ 0DH ; Carregador da Maq2002 Nova
000A * 2 *LF: equ 0AH ; ========== == ======= ====
* 3 * ; Setembro de 2001
0000: 29 00 00 * 4 *Inicio: Mov SP,0
0003: 48 44 00 * 5 * mov CD,Titulo
0006: F5 62 00 * 6 * Call Escreve
0009: 10 10 * 7 *LeEnder:mov B,10H
000B: F5 6B 00 * 8 * Call LeNum
000E: 5E * 9 * push CD
000F: 84 3A * 10 *Proc2pt:cmp A,":"
0011: DC 07 * 11 * jz PrxByte
0013: 84 20 * 12 * cmp A," "
0015: E4 11 * 13 * jnz FimLin
0017: 3C * 14 * in A
0018: D5 F5 * 15 * jr Proc2Pt
001A: F5 6B 00 * 16 *PrxByte:Call LeNum
001D: 84 20 * 17 * cmp A," "
001F: E4 07 * 18 * jnz FimLin
0021: 03 * 19 * mov A,D
0022: 5F * 20 * pop CD
0023: 2A * 21 * mov [CD],A
0024: 7F * 22 * inc CD
0025: 5E * 23 * push CD
0026: D5 F2 * 24 * jr PrxByte
0028: 5F * 25 *FimLin: pop CD
0029: 84 2A * 26 * cmp A,"*"
002B: DC 10 * 27 * jz Coment
002D: 84 74 * 28 * cmp A,"t"
002F: DC 2E * 29 * jz FimProg
0031: 84 54 * 30 * cmp A,"T"
0033: DC 2A * 31 * jz FimProg
0035: 48 5B 00 * 32 * Mov CD,Prompt
0038: F5 62 00 * 33 * Call Escreve
003B: D5 CC * 34 * jr LeEnder
003D: 3C * 35 *Coment: in A
003E: 84 0D * 36 * cmp A,CR
0040: E4 FB * 37 * jnz Coment
0042: D5 C5 * 38 * jr LeEnder
0044: 0D 0A 43 61 * 39 *Titulo: db CR, LF, "Carregador versao 1.0"
0048: 72 72 65 67 61 64 6F 72 20 76 65 72 73 61 6F 20
0058: 31 2E 30
005B: 0D 0A 3E 00 * 40 *Prompt: db CR, LF, ">",0
005F: F4 FF 0F * 41 *FimProg:jmp Para
0062: 07 * 43 *Escreve:mov A,[CD]
0063: E8 05 * 44 * JEQZ A,FimCad
0065: 3D * 45 *EscCar: out A
0066: 7F * 46 * inc CD
0067: 07 * 47 * mov A,[CD]
0068: EC FB * 48 * JNEQZ A,EscCar
006A: FA * 49 *FimCad: RET
006B: 3C * 50 *LeNum: in A ; Recebe a base em B;
006C: 84 20 * 51 * cmp A," " ; Retorna o Separador em A,
006E: DC FB * 52 * jz LeNum ; a base em B e
0070: 84 2D * 53 * cmp A,"-" ; o numero em CD.
0072: 58 * 54 * push F
0073: 48 00 00 * 55 * mov CD,0
0076: 5E * 56 * push CD ; Zera o Numero
0077: 32 * 57 * mov D,B ; Base
0078: E4 01 * 58 * jnZ TstAlg
007A: 3C * 59 *PrxAlg: in A ; Letra
007B: 11 * 60 *TstAlg: mov B,A ; Algarismo
007C: A0 30 * 61 * sub B,"0"
007E: A4 0A * 62 * cmp B,0AH
0080: DB 0A * 63 * jc Ealg
0082: A0 11 * 64 * sub B,"A"-"0"
0084: A4 20 * 65 * cmp B,"a"-"A"
0086: DB 02 * 66 * jc Eletra
0088: A0 20 * 67 * sub B,"a"-"A"
008A: A1 0A * 68 *Eletra: add B,0AH
008C: BC * 69 *EAlg: cmp B,D ; base
008D: E3 0D * 70 * jnc FimNum
008F: 22 * 71 * mov C,B ; Algarismo
0090: 51 * 72 * pop A ; Parte Alta do numero
0091: D0 * 73 * mul A,D ; AB = Parte Alta * Base
0092: 51 * 74 * pop A ; Parte baixa do numero
0093: 52 * 75 * push B ; Seg. parc da nova parte alta
0094: D0 * 76 * mul A,D ; AB = Parte Baixa * Base
0095: B1 * 77 * add B,C ; Soma o algarismo
0096: 55 * 78 * pop C ; Seg. parc da nova parte alta
0097: 93 * 79 * adc A,C ; Soma seg. parc. da nova parte alta
0098: 52 * 80 * push B
0099: 50 * 81 * push A
009A: D5 DE * 82 * JR PrxAlg
009C: 13 * 83 *FimNum: mov B,D
009D: 55 * 84 * pop C
009E: 57 * 85 * pop D
009F: 59 * 86 * pop F
00A0: E4 05 * 87 * jnz Retorna
00A2: 5C * 88 * push AB
00A3: 46 * 89 * mov AB,CD
00A4: 73 * 90 * neg AB
00A5: 4E * 91 * mov CD,AB
00A6: 5D * 92 * pop AB
00A7: FA * 93 *Retorna:RET
0FFF * 94 * ORG 0FFFH
0FFF: FE * 95 *PARA: Halt