7. O PROGRAMA CARREGADOR PARA A MÁQUINA 2002

   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



7.1 ASPECTOS GERAIS

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".




7.3. CARREGANDO PROGRAMAS ARMAZENADOS EM "FITA DE PAPEL"

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