
          ͻ
                    Tutorial de Assembler de Adam Hyde 1.0        
                                                                   
                                  PARTE V                          
                      Traduzido por Renato Nunes Bastos            
          ͼ 
            


Verso   :  1.3
Data     :  15-03-1996
Contato  :  blackcat@vale.faroc.com.au
            http://www.faroc.com.au/~blackcat
;Renato  :  bastos@lci.ufrj.br
            krull@geocities.com
            http://www.geocities.com/SiliconValley/Park/3174


 

Bem, outra semana ou algo assim parece ter passado... Outra semana que eu
deveria ter usado para fazer algo til. De qualquer modo, parece que estes
tutoriais esto ganhando um pouco mais de popularidade, o que  bom.

Eu tenho recebido alguns cdigos demo de algum que parece ter achado um uso 
para os tutoriais. Por favor, se voc tentar algo com ajuda do tutorial,
ou de seu jeito, mande para mim. Eu gosto de ver o que as pessoas tm feito do
meu trabalho, ou apenas quo criativo vocs todos so. Se voc escrever
algo que eu ache til para os outros aprenderem, ou apenas  maneiro, eu vou
colocar na minha pgina da web.

Note que eu inclu um demo starfield neste tutorial dessa semana.
Voc pode rodar STARS.EXE, ou olhar STARS.PAS que  o cdigo fonte.
 s um simples demo, mas pode ser usado para fazer alguns efeitos
interessantes.


Agora, esta semana vamos inicialmente listar um sumrio de todas as instrues
que voc j deveria ter aprendido at agora, e umas novas. Ento vamos ver
como a VGA  arrumada, e cobrir uma rotina simples de linha.


 

         
                                                                   
                     SUMRIO DO CONJUNTO DE INSTRUES             
                                                                   
         



    ADC <DEST>, <FONTE>         - Nome: Soma com Vai-Um
                                   Tipo: 8086+

                                   Descrio: Esta instruo soma <FONTE>
                                   e <DEST> e soma o valor armazenado no
                                   flag de vai-um, que ser um ou zero,
                                   a <DEST> tambm.

                                   Basicamente, DEST = DEST + FONTE + CF

                                   EX.: ADD AX, BX


    ADD <DEST>, <FONTE>         - Nome: Add
                                   Tipo: 8086+

                                   Descrio: Esta instruo soma <FONTE>
                                   e <DEST>, armazenando o resultado em
                                   <DEST>.

                                   EX.: ADD AX, BX


    AND <DEST>, <FONTE>         - Nome: E Lgico
                                   Tipo: 8086+

                                   Descrio: Esta instruo realiza uma
                                   comparao bit a bit de <DEST> e
                                   <FONTE>, armazenando o resultado em
                                   <DEST>.

                                   EX.: AND 0, 0     = 0
                                        AND 0, 1     = 0
                                        AND 1, 0     = 0
                                        AND 1, 1     = 1


    BT <DEST>, <BIT NUMBER>     - Nome: Testa Bit
                                   Tipo: 80386+

                                   Descrio: Esta instruo testa
                                   <BIT NUMBER> de <DEST> que pode
                                   ser um registrador de 16 ou 32 bits ou
                                   posio da memria. Se <DEST>  um 
                                   nmero de 16 bits ento o <BIT NUMBER> pode
                                   ser de 0 a 15, seno, se <DEST>  um
                                   nmero de 32 bits, ento o <BIT NUMBER>
                                   pode ter um valor de 0 a 31.

                                   O valor em <BIT NUMBER> de <DEST> 
                                   ento copiado para o flag de vai-um.

                                   EX.: BT   AX, 3
                                        JC   EraIgualAUm


    CALL <DEST>                 - Nome: Chama Procedimento
                                   Tipo: 8086+

                                   Descrio: Esta instruo simplesmente
                                   chama uma subrotina. Em termos mais
                                   tcnicos, ela pe o endereo da prxima
                                   instruo, IP, na pilha, e seta IP, o
                                   registro de instrues, para o valor
                                   especificado por <DEST>.

                                   EX.: CALL MyProc


    CBW                          - Nome: Converte Byte para Word
                                    Tipo: 8086+

                                    Descrio: Esta instruo extende o
                                               byte em AL para AX.

                                    EX.: MOV   AL, 01h
                                         CBW
                                         ADD   BX, AX   ; Faz algo com AX


    CLC                          - Nome: Limpa Flag de Vai-Um
                                    Tipo: 8086+

                                    Descrio: Esta instruo zera o flag
                                    de vai-um no registrador de flags.

                                    EX.: CLC


    CLD                          - Nome: Limpa Flag de Direo
                                    Tipo: 8086+

                                    Descrio: Esta instruo limpa o
                                    flag de direo no registrador de flags 
                                    para 0. Quando o flag de direo  0,
                                    qualquer instruo de strings incrementa
                                    os registradores de ndice SI e DI.

                                    EX.: CLD


    CLI                          - Nome: limpa Flag de Interrupo
                                    Tipo: 8086+

                                    Descrio: Esta instruo limpa o flag de
                                    interrupo no registrador de flags para
                                    0, assim desabilitando interrupes de
                                    hardware.

                                    EX.: CLI


    CMC                          - Nome: Complementa o Flag de Vai-Um
                                    Tipo: 8086+

                                    Descrio: Esta instruo checa o valor
                                    atual no flag de vai-um.
                                    Se for 0 - transforma em 1 e se for
                                    1 - passa a ser 0.

                                    EX.: BT   AX, 1    ; Testa o bit 1 de AX
                                         JC   EraUm
                                         JMP  Fim

                                        EraUm:
                                        CMC           ; Retorna CF para 0

                                        Fim:


    CMP <VALOR1>, <VALOR2>       - Nome: Comparao Inteira
                                    Tipo: 8086+

                                    Descrio: Esta instruo compara
                                    <VALOR1> e <VALOR2> e reflete a comparao
                                    nos flags.

                                    EX.: CMP AX, BX

                                    Veja tambm as intrues Jcc.


    CWD                          - Nome: Converte Word para Doubleword
                                    Tipo: 8086+

                                    Descrio: Esta instruo extende a
                                    word em AX para o par DX:AX.

                                    EX.: CWD


    DEC <VALOR>                  - Nome: Decrementa
                                    Tipo: 8086+

                                    Descrio: Esta instruo subtrai
                                    um do valor em <VALOR> e armazena
                                    o resultado em <VALOR>.

                                    EX.: DEC AX


    DIV <VALOR>                  - Nome: Diviso sem Sinal
                                    Tipo: 8086+

                                    Descrio: Esta instruo divide
                                    <VALOR> por, ou AX para byte, DX:AX para
                                    word ou EDX:EAX para doubleword.

                                    Para byte, o quociente  retornado em
                                    AL e o resto em AH, para word o
                                    quociente  retornado em AX e o
                                    resto em DX e para DWORD, o
                                    quociente volta em EAX e o
                                    resto em EDX.

                                    EX.: MOV   AX, 12
                                         MOV   BH, 5
                                         DIV   BH
                                         MOV   Quociente, AL
                                         MOV   Resto, AH


    IN <ACUMULADOR>, <PORTA>     - Nome: Entrada de porta de E/S
                                    Tipo: 8086+

                                    Descrio: Esta instruo l um valor
                                    de uma das 65536 portas de hardware 
                                    especificada no <ACUMULADOR>.

                                    AX e AL so comumente usados para portas
                                    de entrada, e DX  comumente usado para
                                    identificar a porta.

                                    EX.: IN    AX, 72h

                                         MOV   DX, 3C7h
                                         IN    AL, DX


    INC <VALOR>                  - Nome: Incrementa
                                    Tipo: 8086+

                                    Descrio: Esta instruo soma um ao
                                    nmero em <VALOR>, e armazena
                                    o resultado em <VALOR>.

                                    EX.: MOV   AX, 13h   ; AX = 13h
                                         INC   AX        ; AX = 14h


    INT <INTERRUPO>            - Nome: Gera uma Interrupo
                                    Tipo: 8086+

                                    Descrio: Esta instruo salva os valores
                                    correntes dos flags e IP na pilha, e ento
                                    chama a <INTERRUPO> baseada no valor de
                                    AH.

                                    EX.:   MOV   AH, 00h   ; Seta o modo de
                                                           ; vdeo
                                           MOV   AL, 13h   ; Modo 13h
                                           INT   10h       ; Gera interrupo


    Jcc                          - Nome: Pula (Jump) se Condio
                                    Tipo: 8086+

   Eu no vou repetir eu mesmo todos os 32, d uma olhada no Tutorial Trs
   a lista completa deles. Tenha em mente que seria uma boa idia chamar 
   CMP, OR, DEC ou algo semelhante antes de usar uma dessas instrues. :)

   EX.: DEC   AX
        JZ    AX_Chegou_A_Zero


    JMP <DEST>                   - Nome: Jump
                                    Tipo: 8086+

                                    Descrio: Esta instruo simplesmente
                                    carrega um novo valor, <DEST>, em IP,
                                    assim transferindo o controle para outra
                                    parte do cdigo.

                                    EX.: JMP   MyLabel


    LAHF                         - Nome: Carega AH com Flags
                                    Tipo: 8086+

                                    Descrio: Esta instruo copia os
                                    bytes mais baixos do registrador de flags
                                    para AH. O contedo de AH vai parecer
                                    com algo semeelhante depois que
                                    a instruo for executada:


              
               Flag  SF  ZF  --  AF  --  PF  --  CF 
              
               Bit   07  06  05  04  03  02  01  00 
              

            Voc pode agora testar os bits individualmente, ou realizar
          uma instruo similar  seguinte para pegar um flag apenas:

          EG: LAHF
              SHR   AH, 6
              AND   AH, 1   ; AH contm o flag ZF.


    LEA <DEST>, <FONTE>          - Nome: Carrega Endereo Efetivo
                                    Tipo: 8086+

                                    Descrio: Esta instruo carrega o
                                    endreo de memria que <FONTE> significa,
                                    em <DEST>.

                                    EX.: eu uso  LEA SI, Str  numa das minhas
                                         procedures que pes uma string na
                                         tela bem rpido.


    LOOP <LABEL>                 - Nome: Decrementa CX e Repete
                                    Tipo: 8086+

                                    Descrio: Esta instruo  uma forma
                                    do loop For...Do que existe na maioria
                                    das linguagens de alto nvel. Basicamente
                                    ele volta ao label, ou segmento de memria
                                    at que CX = 0.

                                    EX.: MOV   CX, 12

                                         FazAlgumaCoisa:
                                           ;...
                                           ;...
                                           ;... Isto ser repetido 12 vezes

                                         LOOP FazAlgumaCoisa


    Lseg <DEST>, <FONTE>         - Nome: Carega Registrador de Segmento
                                    Tipo: 8086+

                                    Descrio: Esta instruo existe de
                                    vrias formas. Todas aceitam  mesma
                                    sintaxe, em que <FONTE> especifica um
                                    ponteiro de 48 bits, consistindo de um
                                    offset de 32 bits e um seletor de 16 bit.
                                    O offset de 32 bis  caregado em 
                                    <DEST>, e o seletor  carregado no
                                    registrador de segmento especificado por
                                    seg.

                                    As seguintes formas existem:

                                    LDS
                                    LES 
                                    LFS     * 32 bits
                                    LGS     * 32 bits
                                    LSS

                                    EX.: LES   SI, Um_Ponteiro


    MOV <DEST>, <FONTE>          - Nome: Move Dados
                                    Tipo: 8086+

                                    Descrio: Esta instruo copia
                                    <FONTE> em <DEST>.

                                    EX.: MOV   AX, 3Eh
                                         MOV   SI, 12h


    MUL <FONTE>                  - Nome: Multiplicao sem Sinal
                                    Tipo: 8086+

                                    Descrio: Esta instruo multiplica
                                    <FONTE> pelo acumulador, que depende
                                    do tamanho de <FONTE>.

                                    Se <FONTE>  um byte ento:

                                    * AL  o multiplicando;
                                    * AX  o produto.

                                    Se <FONTE>  uma word ento:

                                    * AX  o multiplicando;
                                    * DX:AX  o produto.

                                    Se <FONTE>  uma doubleword ento:

                                    * EAX  o multiplicando;
                                    * EDX:EAX  o produto.

                                    OBS.: Os flags so inalterados
                                    excetos para OF e CF, que so
                                    zerados se o byte alto, word ou
                                    dword do produto for 0.

                                    EX.: MOV   AL, 3
                                         MUL   10
                                         MOV   Resultado, AX


    NEG <VALOR>                  - Nome: Nega
                                    Tipo: 8086+

                                    Descrio: Esta instruo subtrai
                                    <VALOR> de 0, resultando na negao
                                    do complemento a dois de <VALOR>.

                                    EX.: MOV   AX, 03h
                                         NEG   AX       ; AX = -3


    NOT <VALOR>                  - Nome: Complemento Lgico
                                    Tipo: 8086+

                                    Descrio: Esta instruo inverte o
                                    estado de cada bit no operando.

                                    EX.: NOT   CX


    OR <DEST>, <FONTE>           - Nome: OU Lgico
                                    Tipo: 8086+

                                    Descrio: Esta instruo realiza uma
                                    operao de OU booleano entre cada bit de
                                    <DEST> e <FONTE>, guardando o resultado
                                    em <DEST>.

                                    EX.: OR 0, 0     = 0
                                         OR 0, 1     = 1
                                         OR 1, 0     = 1
                                         OR 1, 1     = 1


    OUT <PORTA>, <ACUMULADOR>    - Nome: Sada para a Porta
                                    Tipo: 8086+

                                    Descrio: Esta instruo manda para a
                                    sada o valor do acumulador para <PORTA>.
                                    Usando o registrador DX para pasar a porta
                                    OUT, voc pode acessar 65,536 portas.

                                    EX.: MOV   DX, 378h
                                         OUT   DX, AX


    POP <REGISTRADOR>            - Nome: Carega Registrador da pilha
                                    Tipo: 8086+

                                    Descrio: Esta instruo pega o valor
                                    atual do topo da pilha e coloca no
                                    <REGISTRADOR>.

                                    EX.: POP   AX


    POPA                         - Nome: Pega Todos os Registradores Gerais
                                    Tipo: 80186+

                                    Descrio: Esta instruo pega todos os
                                    registradores de uso geral de 16 bits
                                    da pilha, exceto SP.

                                     o mesmo que:

                                    POP   AX
                                    POP   BX
                                    POP   CX
                                    ...

                                    EX.: POPA


    POPF                         - Nome: Pega o valor do topo para Flags
                                    Tipo: 8086+

                                    Descrio: Esta instruo pega o
                                    byte baixo dos flags da pilha.

                                    EX.: POPF


    PUSH <REGISTRADOR>           - Nome: Pe na Pilha o Registrador
                                    Tipo: 8086+

                                    Descrio: Esta instruo pe
                                    <REGISTRADOR> na pilha.

                                    EX.: PUSH  AX


    PUSHA                        - Nome: Pe todos os registradores na pilha
                                    Tipo: 80186+

                                    Descrio: Esta instruo pe todos os
                                    registradores de uso geral de 16 bits
                                    na pilha.

                                     o mesmo que:

                                    PUSH  AX
                                    PUSH  BX
                                    PUSH  CX
                                    ...

                                    EX.: PUSHA


    PUSHF                        - Nome: Pe flags na pilha
                                    Tipo: 8086+

                                    Descrio: Esta instruo pe o 
                                    byte baixo dos flags na pilha.

                                    EX.: PUSHF


    REP                          - Nome: Sufixo de Repetio
                                    Tipo: 8086+

                                    Descrio: Esta instruo repetir
                                    a intruo seguinte o nmero de vezes 
                                    especificado em CX.

                                    EX.: MOV   CX, 6
                                         REP   STOSB    ; Armazena 6 bytes


    RET                          - Nome: Retorno de Subrotina (Near/prximo)
                                    Tipo: 8086+

                                    Descrio: Esta instruo retorna IP
                                    ao valor que ele tinha antes da ltima
                                    instruo CALL. RET, ou RETF para um 
                                    jump distante (far), deve ser chamado
                                    quando se usa assembler puro.

                                    EX.: RET


    ROL <DEST>, <VALOR>          - Nome: Roda  esquerda
                                    Type: 8086+

                                    Descrio: Esta instruo roda
                                    <DEST> <VALOR> vezes. Uma rodada 
                                    realizada shiftando <DEST> uma vez, ento
                                    transfere-se o bit que saiu para 
                                    a posio de mais baixa ordem de <DEST>.

                                    EX.: ROL   AX, 3


    ROR <DEST>, <VALOR>          - Nome: Roda  Direita
                                    Tipo: 8086+

                                    Descrio: Esta instruo roda
                                    <DEST> <VALOR> vezes. Uma rodada 
                                    realizada shiftando <DEST> uma vez, ento
                                    transfere-se o bit que saiu para 
                                    a posio de mais alta ordem de <DEST>.

                                    EX.: ROR    BX, 5


    SAHF                         - Nome: Armazena AH nos Flags
                                    Tipo: 8086+

                                    Descrio: Esta instruo carrega o
                                    contedo do registrador AH nos bits
                                    7, 6, 4, 2 e 0 do registrador de flags.

                                    EX.: SAHF


    SBB <DEST>, <FONTE>          - Nome: Subtrai com "pede-emprestado"
                                    Tipo: 8086+

                                    Descrio: Esta instruo subtrai
                                    <FONTE> de <DEST>, e decrementa
                                    <DEST> de uma unidade de o flag de vai-um
                                    estiver setado, armazenando o resultado
                                    em <DEST>.

                                   Basicamemte, <DEST> = <DEST> - <FONTE> - CF

                                    EX.: SBB   AX, BX


    SHL <DEST>, <VALOR>         - Nome: Shift  esquerda
                                   Tipo: 8086+

                                   Descrio: Esta instruo desloca <DEST>
                                    esquerda de <VALUE> unidades.
                                   Eu no vou entrar em detalhes
                                   sobre a teoria disso de novo.
                                   Se voc no tem certeza do que esta
                                   instruo faz, por favor, leia o Tutorial
                                   Quatro.

                                   EX.: SHL   AX, 5


    SHR <DEST>, <VALOR>         - Name: Shift  direita
                                   Type: 8086+

                                   Descrio: Esta instruo desloca <DEST>
                                    direita de <VALUE> unidades. Por favor
                                   veja o Tutorial Quatro para a teoria dos
                                   shifts.

                                   EX.: SHR   DX, 1


    STC                         - Nome: Seta o flag de vai-um (Carry Flag)
                                   Tipo: 8086+

                                   Descrio: Esta instruo seta o valor 
                                   do carry flag para um.

                                   EX.: STC


    STD                         - Nome: Seta o flag de direo
                                   Tipo: 8086+

                                   Descrio: Esta instruo seta o
                                   valor do flag de direo para um. Isto 
                                   instrui a todas operaes a decrementar
                                   os registradores de ndice.

                                   EX.: STD
                                        REP STOSB   ; DI est sendo
                                                    ; decrementado


    STI                         - Nome: Seta Flag de Interrupo
                                   Tipo: 8086+

                                   Descrio: Esta instruo seta o
                                   valor do flag de interrupo para um, assim
                                   permitindo que interrupes de hardware
                                   ocorram.

                                   EX.: CLI      ; Pra interrupes
                                        ...      ; Realiza uma funo crucial 
                                        STI      ; Habilita interrupes


    STOS                        - Nome: Armazena String
                                   Tipo: 8086+

                                   Descrio: Esta instruo existe nas 
                                   seguintes formas:

                                   STOSB      - Armazena um byte        - AL
                                   STOSW      - Armazena uma word       - AX
                                   STOSD      - Armazena uma doubleword - EAX

                                   As instrues escrevem o contedo atual
                                   do acumulador para a posio de memria
                                   apontada por ES:DI. Ento ela incrementa
                                   ou decrementa DI de acordo com o operando
                                   usado, e o valor do flag de direo.

                                   Ex.: MOV   AX, 0A000h
                                        MOV   ES, AX
                                        MOV   AL, 03h
                                        MOV   DI, 0
                                        STOSB          ; Armazena 03 em ES:DI,
                                                       ; que  o topo da tela
                                                       ; em modo 13h


    SUB <DEST>, <FONTE>         - Nome: Subtrao
                                   Tipo: 8086+

                                   Descrio: Esta instruo subtrai
                                   <FONTE> de <DEST>, armazenando o resultado
                                   em <DEST>.

                                   EX.: SUB   ECX, 12


    TEST <DEST>, <FONTE>        - Nome: Testa Bits
                                   Tipo: 8086+

                                   Descrio: Esta instruo realiza uma
                                   operao AND  bit-a-bit em  <FONTE> e
                                   <DEST>. O resultado refflete nos flags,
                                   e eles so so setados como se fizssemos
                                   um AND.

                                   EX.: TEST   AL, 0Fh   ; Checa se algum
                                                         ; bits est setado 
                                                         ; no mais baixo
                                                         ; nibble de AL


    XCHG <VALOR1>, <VALOR2>     - Nome: Troca
                                   Tipo: 8086+

                                   Descrio: Esta instruo troca os
                                   valores de <VALOR1> e <VALOR2>.

                                   EX.: XCHG   AX, BX


    XOR <DEST>, <FONTE>         - Nome: OU Exclusivo Lgico
                                   Tipo: 8086+

                                   Descrio: Esta instruo realiza
                                   um OU exclusivo bit-a-bit em
                                   <FONTE> e <DEST>. A operao 
                                   definida como segue:

                                   XOR   0, 0    = 0
                                   XOR   0, 1    = 1
                                   XOR   1, 0    = 1
                                   XOR   1, 1    = 0

                                   EX.: XOR   AX, BX


 

Ufa! Que monto existem, e ns s vimos as bsicas! No se espera que voc 
entenda cada uma delas.  Voc provavelmente viu expresses como 'Complemento
a Dois', e pensou - "Que  que essa merda quer dizer?".

No se preocupe com isso por enquanto.  Vamos continuar normalmente, e
introduzir as novas instrues acima uma por uma, explicando-as quando o
fizermos. Se voc j as entende, isso  um bnus. Voc vai notar que havia
muitas instrues acima, do 8086. H, na verdade, poucos casos em que 
necessrio usar uma instruo do 386 ou 486, muito menos do Pentium.

De qualquer modo, antes de avanar com a VGA, eu vou s listar a velocidade 
em que cada instruo acima  executada, assim voc pode usar isso para
ver como as rotinas em Assembler so rpidas.


 

 Instruo         Clocks no 386         Clocks no 486

 

    ADC                  2                     1
    ADD                  2                     1
    AND                  2                     1
    BT                   3                     3
    CALL                 7+m                   3
    CBW                  3                     3
    CLC                  2                     2
    CLD                  2                     2
    CLI                  5                     3
    CMC                  2                     2
    CMP                  2                     1
    CWD                  2                     3
    DEC                  2                     1
    DIV                  -                     -
        - Byte           9-14                  13-18
        - Word           9-22                  13-26
        - DWord          9-38                  13-42
    IN                   12/13                 14
    INC                  2                     1
    INT                  depende               depende
    Jcc                  -                     -
        - Em loop        7+m                   3
        - No loop       3                     1
    JMP                  7+m                   3
    LAHF                 2                     3
    LEA                  2                     1
    LOOP                 11                    6
    Lseg                 7                     6
    MOV                  2                     1
    MUL                  -                     -
        - Byte           9-14                  13-18
        - Word           9-22                  13-26
        - DWord          9-38                  13-42
    NEG                  2                     1
    NOT                  2                     1
    OR                   2                     1
    OUT                  10/11                 16
    POP                  4                     1
    POPA                 24                    9
    POPF                 5                     9
    PUSH                 2                     1
    PUSHA                18                    11
    PUSHF                4                     4
    REP                  depende               depende
    RET                  10+m                  5
    ROL                  3                     3
    ROR                  3                     3
    SAHF                 3                     2
    SBB                  2                     1
    SHL                  3                     3
    SHR                  3                     3
    STC                  2                     2
    STD                  2                     2
    STI                  3                     5
    STOS                 4                     5
    SUB                  2                     1
    TEST                 2                     1
    XCHG                 3                     3
    XOR                  2                     1

 Obs.: m = Nmero de componentes na prxima instruo executada.

Ugh, eu nunca quero ver outro clock de novo! Agora, continuemos com o
divertido - VGA!


 

Voc provavlmente j notou que sua placa de vdeo tem mais que 256K de RAM.
(se no tem, ento estes tutoriais no so provavelmente para voc.) Mesmo que
voc tenha s 256K de RAM, como meu velho 386, voc ainda  capaz de entrar
no modo 13h - 320x200x256. Porm, isto levanta algumas quetes.

Multiplique 320 por 200 e voc vai notar que voc s precisa de 64,000 bytes
de memria para armazenar uma tela simples. (A VGA na verdade nos d 64K,
que  65,536 bytes para quem no sabe.) O que aconteceu com os restantes 192K?

Bem, a VGA  na verdade arrumada em planos de bits, como isso:


                     3
                   2 
                 1  
               0   
                                  
                                  
                    64,000       
                                
                               
               

Cada plano sendo de 64,000 bytes.  Aqui est como isso funciona:

 Um pixel at 0, 0  mapeado no plano 0 no offset 0;
 Um pixel at 1, 0  mapeado no plano 1 no offset 0;
 Um pixel at 2, 0  mapeado no plano 2 no offset 0;
 Um pixel at 3, 0  mapeado no plano 3 no offset 0;
 Um pixel at 4, 0  mapeado no plano 0 no offset 1   ... e assim por diante...

Por causa de os pixels serem encadeados atravs dos 4 planos,  impossvel
usar mltiplas pginas no modo 13h sem ter que to usar uma tela virtual,
ou algo do tipo.

O mapeamento automtico dos pixels  feito todo pela placa de vdeo,
de modo que voc pode trabalhar de olhos fechados sem saber dos 4 planos de
bits se voc quiser.

Vamos ver como voc pode contornar essa situao, entrando num modo especial,
conhecido como Modo X, mais tarde, mas por enquanto, vamos s ver o que
podemos fazer no velho modo 13h.


 

         
                                                                   
                           DESENHANDO LINHAS                       
                                                                   
         


Passamos um pouco da tamanho do tamanho que eu tinha planejado para este
tutorial, e eu pretendo falar do Algoritmo de Retas de Bresenham, mas isso vai
ter que esperar a semana que vem. No entanto, vou cobrir como desenhar um
linha reta horzontal simples em Assembler.


  Um Rotina em Assembler para Retas Horizontais:
 ------------------------------------------------

Primeiramente vamos precisar de apontar ES para a VGA.

Isso deve resolver:

   MOV   AX, 0A000h
   MOV   ES, AX

Agora, precisaremos de ler os valores de X1, X2 e Y nos registradores, ento
algo assim deveria funcionar:

   MOV   AX, X1    ; AX  igual ao valor X1 agora
   MOV   BX, Y     ; BX  igual ao valor Y agora
   MOV   CX, X2    ; CX  igual ao valor X2 agora

Ser preciso calcular o tamanho da linha, ento vamos usar CX para
guardar isso, sendo que:  i) CX j tem o valor de X2, e  ii) vamos usar
uma instruo REP, que usar CX como contador.

   SUB   CX, AX    ; CX = X2 - X1

Agora vamos precisar de calcular o DI para o primeiro pixel que plotaremos,
ento vamos fazer o que fizemos na rotina de PutPixel:

   MOV   DI, AX    ; DI = X1
   MOV   DX, BX    ; DX = Y
   SHL   BX, 8     ; Shift Y  esquerda 8
   SHL   DX, 6     ; Shift Y  esquerda 6
   ADD   DX, BX    ; DX = Y SHL 8 + Y SHL 6
   ADD   DI, DX    ; DI = Y x 320 + X

Temos o offset do primeiro pixel agora, ento tudo o que temos que fazer 
colocar a cor que queremos desenhar em AL, e usar STOSB para plotar o resto
da linha.

   MOV   AL, Cor   ; Move a cor a plotar em AL
   REP   STOSB     ; Plota CX pixels

Note que usamos STOSB porque ele vai incrementar DI para ns, assim
economizando um monte de MOV's e INC's. Agora, dependendo de que linguagem
voc vai usar para implementar, voc vai chegar a algo assim:


   void Draw_Horizontal_Line(int x1, int x2, int y, unsigned char color)
   {
   _asm
      {
      mov   ax, 0A000h
      mov   es, ax        ; Aponta ES para a VGA

      mov   ax, x1        ; AX = X1
      mov   bx, y         ; BX = Y
      mov   cx, x2        ; CX = X2

      sub   cx, ax        ; CX = Diferena de X2 e X1

      mov   di, ax        ; DI = X1
      mov   dx, bx        ; DX = Y
      shl   bx, 8         ; Y SHL 8
      shl   dx, 6         ; Y SHL 6
      add   dx, bx        ; DX = Y SHL 8 + Y SHL 6
      add   di, dx        ; DI = Offset do primeiro pixel

      mov   al, color     ; Pe a cor a plotar em AL
      rep   stosb         ; Desenha a linha
      }
   }


 

Agora j vimos como desenhar uma linha horizontal simples. A rotina acima
no  cegamente rpida, mas no  de toda m. S de mudar o clculo da
parte de DI como na PutPixel que eu dei no Tutorial Dois, j dobraria
a velocidade desta rotina.

Minha prpria rotina de linha horizontal  provavelmente cerca de 4 a 5 vezes
mais rpida que esta, assim, no futuro, eu vou lhe mostrar como otimizar essa
rotina por completo. Semana que vem vamos ver como pegar e acertar a palette,
e como podemos desenhar crculos. Sinto muito se no fiz isso nesse
tutorial, mas ele cresceu um pouco demais...


 COISAS PARA FAZER:
--------------------

   1) Escreva um rotina para linhas verticais baseada na rotina acima. Dica:
      Voc precisa incrementar DI de 320 em algum lugar.

   2) Volte  lista das instrues de Assembler, e aprenda quantas puder.

   3) D uma olhda no Starfield que eu escrevi, e tente corrigir os bugs dele.
      Veja o que voc pode fazer com ele.


 

Desculpem-me de novo se no inclu as coisas que eu disse que ia escrever
na semana passada, mas como eu disse, o tutorial simplesmente cresceu,
e eu estou um pouco atrasado com uns projetos em que eu devia estar
trabalhando.


No prximo tutorial vamos ver:

    Algoritmos de linha e exemplos;
    Um algoritmo de crculo;
    A palette;
    Alguma coisa mais que eu achar que voc deva saber...


Se voc deseja ver um tpico discutido num tutorial no futuro, escreva-me, e
eu vou ver o que eu posso fazer.


 

No perca!!! Baixe o tutorial da prxima semana na minha homepage:

   http://www.faroc.com.au/~blackcat
   http://www.geocities.com/SiliconValley/Park/3174

Vejo vocs na prxima semana!

- Adam.
- Renato Nunes Bastos
