Curso Fudeba de ASM

 


Aula 4: Começando a pensar em ASM.

  Bem, chegou a hora do desapego. Esta aula é apenas uma parte do que originalmente havia sido previsto para a Aula 4, pois achei que estava muito pesada. Nesta aula vamos começar a tomar algum contato com uma forma um pouco mais "rudimentar" de raciocínio: vamos brincar de pensar igual ao computador. Pode parecer bobeira, mas tudo que parece muito difícil de programar pensando como "gente" fica mais simples quando pensado como se fossemos o computador. Nesta aula é que os programadores de BASIC começaram a sentir alguma diferença mais fundamental com o que estão habituados, mas hey, continua não sendo um bicho nem de duas cabeças.

  Primeiramente veremos como trabalhar com repetição de instruções e nas próximas aulas usaremos isso para imprimir varias mensagens diferentes usando apenas um loop. Nesta aula vamos aprender também a usar o FuDebug para ajudar a resolver os paus de nossos programas.

  Brincando de repetir uma tarefa

  Você deve ter reparado que nos programas anteriores escrevemos uma seqüência de frases, não é? Bem, mas e se ao invés de imprimirmos varias frases, quiséssemos repetir varias vezes, digamos, 5 vezes, a mesma frase? Bem, nosso programa ficaria mais ou menos assim...

--- Cortar Aqui ---
BDOS    EQU     5

STROUT  EQU     9

START:
        ; Mostra informações do programa e faz pergunta
        LD      DE,NOMEDOPRG            ; Indica texto do nome do programa
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,AUTOR                ; Indica texto do nome do autor
        CALL    MOSTRATXT               ; Mostra texto

        LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto

        JP      0                       ; Volta ao MSX-DOS


;------
; MOSTRATXT - Função que mostra um texto cuja seqüência é terminada por '$'.
;    Entrada: DE - Aponta para seqüência a ser mostrada, terminada por '$'
;------
MOSTRATXT:
        LD      C,STROUT                ; Indica função de mostrar texto do BDOS
        CALL    BDOS                    ; Manda o BDOS executar.
        RET                             ; Retorna

NOMEDOPRG:      DB      'Programa 4 - Brincando com loops',13,10,'$'
AUTOR:          DB      '  Por Daniel Caetano',13,10,10,'$'
FUDEBA:         DB      'O DalPoz é um fudeba!',13,10,'$'

        END
--- Cortar Aqui ---

   Simples, melzinho na chupeta agora que estamos todos craques em ASM. Mas vocês concordam que isso ficou com uma aparência meio "burra"? Estamos repetindo 5 vezes a mesma coisa! Uma alternativa seria fazer o seguinte:

--- Cortar Aqui ---
BDOS    EQU     5

STROUT  EQU     9

START:
        ; Mostra informações do programa e faz pergunta
        LD      DE,NOMEDOPRG            ; Indica texto do nome do programa
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,AUTOR                ; Indica texto do nome do autor
        CALL    MOSTRATXT               ; Mostra texto

        CALL    TXTFUDEBA               ; Imprime texto fudeba
        CALL    TXTFUDEBA               ; Imprime texto fudeba
        CALL    TXTFUDEBA               ; Imprime texto fudeba
        CALL    TXTFUDEBA               ; Imprime texto fudeba
        CALL    TXTFUDEBA               ; Imprime texto fudeba

        JP      0                       ; Volta ao MSX-DOS

;------
; TXTFUDEBA - Imprime texto fudeba na tela
;------
MOSTRATXT:
        LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        RET

;------
; MOSTRATXT - Função que mostra um texto cuja seqüência é terminada por '$'.
;    Entrada: DE - Aponta para seqüência a ser mostrada, terminada por '$'
;------
MOSTRATXT:
        LD      C,STROUT                ; Indica função de mostrar texto do BDOS
        CALL    BDOS                    ; Manda o BDOS executar.
        RET                             ; Retorna

NOMEDOPRG:      DB      'Programa 4 - Brincando com loops',13,10,'$'
AUTOR:          DB      '  Por Daniel Caetano',13,10,10,'$'
FUDEBA:         DB      'O DalPoz é um fudeba!',13,10,'$'

        END
--- Cortar Aqui ---

   Já ficou melhor, não? De fato, essa segunda solução é melhor em termos de tamanho, mas na verdade, se você pensar com carinho, verá que ela ficou mais lenta, porque agora o processador tem que pular de um lado para outro muito mais vezes do que antes. Assim, aqui aparece um conceito importante: se você precisa de velocidade em um determinado trecho do programa, só o subdivida em funções se:

   Fora essas situações, evite simplesmente sair dividindo tudo. E o caso de nosso programa é um desses em que ficar enchendo de função não tá melhorando muito. Tá diminuindo o tamanho de uma quantia ínfima e tá deixando ele mais lento, alem de deixando ele mais difícil de ler, pois ele tá cada vez mais espalhado, com funções que fazem tarefas cada vez menores e mais especializadas.

   Alem disso, *existe* um jeito diferente de fazer isso. Um jeito que nos dá mais maleabilidade como veremos posteriormente, alem de trazer um ganho de desempenho e economizar ainda MAIS espaço. COMO?!? É simples! Dizendo pro Z80 repetir os comandos! Ele sabe fazer isso muito bem!

   O comando que faz isso é o DJNZ, um tipo especial de Jump. O que ele significa eu entro em mais detalhes depois. Mas a idéia é mais ou menos essa:

LOOP:   ASM1
        ASM2
        ASM3 ...
        DJNZ    LOOP

   Ou seja, o DJNZ vai fazer ele repetir tudo que está entre o DJNZ e a definição LOOP. Epa, mas então o LOOP é uma função também? Afinal, eu defini ele com os 2 pontinhos na frente! Bem, digamos que não. Eu menti pra vocês. Colocar esses dois pontinhos na frente não significa que é uma função, mas sim significa que isso é uma ETIQUETA (Label, em inglês). Ora, se você pensar que uma etiqueta, na vida real, serve para a gente identificar as coisas, pro assemblador é a mesma coisa. Ou seja, essa "etiqueta" indica pro assemblador onde estão as coisas. Assim, quando você usa:

CALL FUNCAO

   Ele vai procurar pela etiqueta

FUNCAO:

   E vai executar a partir de então. E é por isso, então, que toda a função começa com uma etiqueta (pra que seja possível você mandar o Z80 pular pra lá!). No entanto, você pode colocar etiquetas onde quiser, mesmo no meio de funções. Isso é útil em diversos casos, como neste do DJNZ. O DJNZ diz mais ou menos assim pro processador: "Repete tudo que estiver entre esta etiqueta e eu". E o Z80, como é muito obediente, vai lá e faz, sem questionar.

   Assim, como ficaria nosso programa? Bem, o que queremos repetir é o seguinte:

        LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto

   Que havíamos até separado em uma função (mas vamos voltar atras). Então, se queremos repetir isso, devemos usar um trecho mais ou menos assim:

LOOP:   LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        DJNZ    LOOP                    ; Repete os comandos LD DE,FUDEBA e CALL
MOSTRATXT

   Não é? Sim! É! Vamos inserir isso no programa, que fica agora assim:

--- Cortar Aqui ---
BDOS    EQU     5

STROUT  EQU     9

START:
        ; Mostra informações do programa e faz pergunta
        LD      DE,NOMEDOPRG            ; Indica texto do nome do programa
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,AUTOR                ; Indica texto do nome do autor
        CALL    MOSTRATXT               ; Mostra texto

LOOP:   LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        DJNZ    LOOP                    ; Repete os comandos LD DE,FUDEBA e CALL
MOSTRATXT

        JP      0                       ; Volta ao MSX-DOS


;------
; MOSTRATXT - Função que mostra um texto cuja seqüência é terminada por '$'.
;    Entrada: DE - Aponta para seqüência a ser mostrada, terminada por '$'
;------
MOSTRATXT:
        LD      C,STROUT                ; Indica função de mostrar texto do BDOS
        CALL    BDOS                    ; Manda o BDOS executar.
        RET                             ; Retorna

NOMEDOPRG:      DB      'Programa 4 - Brincando com loops',13,10,'$'
AUTOR:          DB      '  Por Daniel Caetano',13,10,10,'$'
FUDEBA:         DB      'O DalPoz é um fudeba!',13,10,'$'

        END
--- Cortar Aqui ---

   E vejam como ficou mais limpo! Notem que continua existindo um pulo, como no caso da função. No entanto, quando transformamos em função tivemos que gastar espaço com 5 chamadas à função (agora esse espaço foi economizado) e, ainda no caso da função, havia um pulo adicional: se fomos, tivemos que voltar (com o RET). Ou seja, para cada chamada à função tínhamos DOIS pulos, que agora virou apenas 1 (ele pula da posição do DJNZ para a posição da etiqueta LOOP).

   Assemblem isso com o M80/L80, usando o CL80 e rodem no BrMSX. E o que vocês viram? Creio que funcionou, em parte. (^= Vocês devem ter notado que, ao invés de repetir 5 vezes a frase, esta ficou se repetindo milhares de vezes... infinitas, na verdade. Bem, o que está faltando? Dissemos ao Z80 para REPETIR um trecho de código, mas não dissemos para ele QUANTAS vezes repetir.

   O comando DJNZ significa "Decrement and Jump if Not Zero" ou, em português, subtraia 1 e pule pra etiqueta indicada se o resultado não for zero. Até ai', tudo bem.... Mas subtrai 1 de ONDE? Eu fui maldoso e não contei pra vocês que essa informação precisa ser colocada no registrador B. Quando chegar no DJNZ, ele vai fazer o seguinte:

        B = B - 1

(subtraiu 1 de B)

        B = 0?

   Se NÃO, ele pula para a etiqueta (Decrement and Jump if Not Zero). Se B era igual a zero, no entanto, a instrução é simplesmente ignorada e o programa segue adiante. Assim, devemos colocar no registrador B o numero de vezes que queremos que a coisa se repita. Vamos, então, mudar o programa, acrescentando um

        LD      B,5

   Pra indicar isso. O programa fica então assim:

--- Cortar Aqui ---
BDOS    EQU     5

STROUT  EQU     9

START:
        ; Mostra informações do programa e faz pergunta
        LD      DE,NOMEDOPRG            ; Indica texto do nome do programa
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,AUTOR                ; Indica texto do nome do autor
        CALL    MOSTRATXT               ; Mostra texto

LOOP:   LD      B,5                     ; Indica repetição de 5 vezes.
        LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        DJNZ    LOOP                    ; Repete os comandos LD DE,FUDEBA e CALL
MOSTRATXT

        JP      0                       ; Volta ao MSX-DOS


;------
; MOSTRATXT - Função que mostra um texto cuja seqüência é terminada por '$'.
;    Entrada: DE - Aponta para seqüência a ser mostrada, terminada por '$'
;------
MOSTRATXT:
        LD      C,STROUT                ; Indica função de mostrar texto do BDOS
        CALL    BDOS                    ; Manda o BDOS executar.
        RET                             ; Retorna

NOMEDOPRG:      DB      'Programa 4 - Brincando com loops',13,10,'$'
AUTOR:          DB      '  Por Daniel Caetano',13,10,10,'$'
FUDEBA:         DB      'O DalPoz é um fudeba!',13,10,'$'

        END
--- Cortar Aqui ---

  Assemble novamente e rode.

   O QUE?!? Continuou dando problema? Bem, vamos passo a passo ver o que está acontecendo. Assim que você executa o programa ele vai executar:

        LD      DE,NOMEDOPRG            ; Indica texto do nome do programa
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,AUTOR                ; Indica texto do nome do autor
        CALL    MOSTRATXT               ; Mostra texto

   Até aqui nada de anormal. Em seguida, ele executa:

        LOOP:   LD B,5 			; Indica repetição de 5 vezes. 

   Na linha acima indica numero de vezes igual a 5. Portanto, B indica 5 neste momento.

        LD 	DE,FUDEBA 		; Indica texto fudeba CALL MOSTRATXT ; Mostra texto 

   Aqui ele aponta o texto e mostra o texto. B ainda indica 5.

        DJNZ 	LOOP 			; Repete os comandos LD DE,FUDEBA e CALL MOSTRATXT 

   No DJNZ, o valor de B é decrementado (subtraído de uma unidade). Ou seja, com a execução deste comando, B passa a conter o valor 4. Ainda no DJNZ é verificado se 4 = 0? Como não, ele pula para o label LOOP, e temos em seguida:

        LOOP:   LD      B,5                     ; Indica repetição de 5 vezes.

   Que faz B = 5 de novo! Epa, isso está errado! Assim o B nunca vai chegar a zero! E porque isso tá ocorrendo? Porque colocamos o LD B,5 dentro do loop, e isso está, logicamente, errado! A solução é mudar o loop para:

        LD      B,5                     ; Indica repetição de 5 vezes.
LOOP:   LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        DJNZ    LOOP                    ; Repete os comandos LD DE,FUDEBA e CALL
MOSTRATXT

   Ou seja, com o B FORA do loop. Se você fizer a "emulação de cabeça" que eu fiz há pouco verá que agora sim o valor de B vai decrescendo... O programa deve estar assim agora:

--- Cortar Aqui ---
BDOS    EQU     5

STROUT  EQU     9

START:
        ; Mostra informações do programa e faz pergunta
        LD      DE,NOMEDOPRG            ; Indica texto do nome do programa
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,AUTOR                ; Indica texto do nome do autor
        CALL    MOSTRATXT               ; Mostra texto

        LD      B,5                     ; Indica repetição de 5 vezes.
LOOP:   LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        DJNZ    LOOP                    ; Repete os comandos LD DE,FUDEBA e CALL
MOSTRATXT

        JP      0                       ; Volta ao MSX-DOS


;------
; MOSTRATXT - Função que mostra um texto cuja seqüência é terminada por '$'.
;    Entrada: DE - Aponta para seqüência a ser mostrada, terminada por '$'
;------
MOSTRATXT:
        LD      C,STROUT                ; Indica função de mostrar texto do BDOS
        CALL    BDOS                    ; Manda o BDOS executar.
        RET                             ; Retorna

NOMEDOPRG:      DB      'Programa 4 - Brincando com loops',13,10,'$'
AUTOR:          DB      '  Por Daniel Caetano',13,10,10,'$'
FUDEBA:         DB      'O DalPoz é um fudeba!',13,10,'$'

        END
--- Cortar Aqui ---

   Assemble seu programinha e rode no BrMSX e veja que agora o programa roda perfeitamente!

   O QUE!?! Não rodou? Poxa, mas não tem nenhum erro de lógica! hummm... Como fazemos para diagnosticar esse problema? De repente até fazendo a "emulação de   cabeça" a gente ache o problema, mas... poxa, isso dá trabalho pra caramba! Não tem uma ferramenta que faca isso pra gente? UAI, e não tem? Claro que tem! E vocês já a estão usando. É o BrMSX. Pra que usar um "emulador de cabeça" se temos um eletrônico, prontinho?

   Vamos usar o BrMSX então pra descobrir porque nosso programa não está funcionando, mesmo que aparentemente deveria estar.

   Aprendendo a usar o FuDebug

   Entre no BrMSX normalmente até ele entrar no MSX-DOS, mas ainda NÃO rode o programa. Antes precisamos tomar algumas precauções e conhecer alguns detalhes.

   Antes de mais nada pressione F10. Isso vai entrar na tela 1 do FuDebug. Tem um monte de numero aí, não? Tem, pois é. Esta tela é mais ou menos assim:


   BrMSX debugger                            Z80                       VDP PSG  
                                             AF=0042  AF'=01A8    Reg0  00  55  
   10DC> 28 FB        JR Z,10D9              BC=00FF  BC'=0019    Reg1  F0  00  
   10DE  CD 27 0A     CALL 0A27              DE=007C  DE'=0000    Reg2  00  00  
   10E1  21 9B FC     LD HL,FC9B             HL=0304  HL'=E0AB    Reg3  00  00  
   10E4  7E           LD A,(HL)              IX=009F              Reg4  01  00  
   10E5  FE 04        CP 04                  IY=BB80  SZ5H3VNC    Reg5  00  00  
   10E7  20 02        JR NZ,10EB             PC=10DC  01000010    Reg6  00  00  
   10E9  36 00        LD (HL),00             SP=EAEF              Reg7  F1  B8  
   10EB  2A FA F3     LD HL,(F3FA)           I=00 EI  IM1 R=63    Reg8  00  00  
   10EE  4E           LD C,(HL)              PPI       MegaROM    Reg9  00  00  
   10EF  CD C2 10     CALL 10C2                        0000 00    RegA  00  00  
   10F2  22 FA F3     LD (F3FA),HL           A=A8      2000 00    RegB  00  0B  
                                             C=5A      4000 00    RegC  00  00  
   Memory                                              6000 01    RegD  00  00  
   0000 F3 C3 D7 02 BF 1B 98 98 ........     Page0=0   8000 02    RegE  00  00  
   0008 C3 83 26 00 C3 B6 01 00 ..&.....     Page1=2   A000 03    RegF  00  CF  
   0010 C3 86 26 00 C3 D1 01 00 ..&.....     Page2=2   C000 00                  
   0018 C3 45 1B 00 C3 17 02 00 .E......     Page3=2   E000 00    PSG addr  0E  
   BrMSX settings                                                               
  Resolution: 320x200  Frame skipping: 0001  Bar Graph: OFF  Emulation: NORMAL  
  Joy: -  Sound: ON   VSync: OFF  Session: SINGLE  COM: 1  Video Cache: ON      
  Command:                                                         SCC: OFF   
  

   E pode ser dividida basicamente em três partes:

   É nesse lugar que a maioria da atividade de debug acontece. Acostume-se com a cara dele. Aperte S para voltar à emulação. Rode o seu programa. Ele vai começar a mostrar infinitamente a frase "DalPoz é fudeba", como fazia antes. Agora, pressione F10.

   Você deve aparecer na tela do FuDebug... mas... e aí? Onde tá o meu programa no meio desse lixo todo? Hummm... Você pode tentar procurar usando as teclas pra cima e para baixo. Você vai ver que a seção "BrMSX debugger" mexe. Nesta seção, todos os valores estão em hexadecimal. Você encontra, da esquerda para a direita, o endereço da memória, os bytes que compõem a instrução, e mais `a direita da seção o MNEMONICO ASSEMBLY da instrução. Mas isso é demorado. Pra pular para uma posição de memória especifica você pode usar o comando U (Unassemble) do FuDebug. Digite:

        U 0100

   E veja! Ele pulou direto para a posição 0100 da memória. Melhorou bastante, né? Mas onde está o meu programa? Difícil dizer. Na verdade sabemos que ele está em um lugar especifico (já conto pra vocês), mas ele pode não estar visível no momento (como em geral não vai estar). Em 99,99% dos casos o MSX estará processando algumas informações que nada tem a ver com o seu programa. Essa informações estão, em geral, na BIOS do seu MSX. A BIOS contem programas, como o seu, dentro, mas ela fica escondida em um lugar. Se você observar na Janela PPI, notará que existem as seguintes indicações:

        Page 0
        Page 1
        Page 2
        Page 3

   Certo? Mas o que significa isso? Bem, vamos com calma. Lembra-se que na primeira aula eu disse que a folha de papel do MSX tinha 65536 lugares para escrever letrinhas? Então, eu menti de novo. Na verdade, não é uma folha, mas sim duas, frente e verso. Ou seja, temos 4 paginas, cada uma podendo ter até 16384 letrinhas. Uau! Mas pra que isso serve? Pra muita coisa como vamos ver já. Antes gostaria de fazer um parêntese: apesar de PAGINA ser a nomenclatura padronizada para isso no MSX1, devido a mudanças na estruturação do MSX2 a palavra PAGINA foi usada para OUTRA coisa. Vamos chamar essas 4 "coisas" de FRAMES (molduras) como ficou padronizado no MSX2 e superiores pelo MSX2 Technical Handbook. Assim, o MSX tem 4 frames, cada um podendo ter até 16386 bytes, ou seja, cada frame tem 16384 posições de memória, ou 16Kb. Alem disso, você deve ter notado que os MSX em geral possuem vários conectores de cartuchos (chamados SLOTS). Apesar de você só ver 2, na verdade existem 4 (dois deles costumam ser usados internamente, e nos já veremos com o que). Bem, pense agora que você pode ter expansões de memória conectados nesses slots, sejam elas RAM (mais memória pra você brincar) ou ROM (funções pre-prontas, como as do MSX-DOS, que ficam no chamado BDOS, ou as da própria BIOS). Agora, eu te digo que seu MSX *realmente* tem um monte de expansões ligadas. Em geral os slots que aparecem pra fora são o slot 1 e o 2. Mas que fim levaram os slots 0 e 3? Bem, é aí que entra a manha: o slot 0 tem ligado nele de fabrica a BIOS e o BASIC, enquanto o slot 3 costuma vir ligado com a RAM. Note que, tirando a necessidade da BIOS estar no slot 0, essa configuração não é totalmente obrigatório (embora seja seguida pela maioria das maquinas). E... tanto essa configuração não é 100% padrão que existem computadores que vêem com a BIOS no slot 0, RAM no Slot 2 e os slots 1 e 3 aparecem para fora no micro. E o Expert, emulado pelo BrMSX, é um deles.

   Bem, em algum lugar a gente precisa dizer pro MSX em que slot está a RAM/ROM que queremos usar... E é pra isso que temos a memória do MSX dividida em 4 FRAMES de 16Kb: para que cada um deles possa conter dados de diferentes slots, sem que o Z80 precise se preocupar com "onde estou lendo esse dado?" Essa configuração é feita pela PPI, um processador externo ao Z80, que é quem faz essa gambiarra pra podermos ter essa facilidade de ter cada frame da memória do Z80 mostrando dado de um slot diferente.

   E o que isso tudo tem a ver com o FuDebug? Bem, se você olhar, na seção PPI, os valores que estão em frente à

        Page 0
        Page 1
        Page 2
        Page 3

   Se você estiver executando o programa, verá que em 99,99% dos casos a configuração esta:

        Page 0=0
        Page 1=2
        Page 2=2
        Page 3=2

(se não estiver, aperte S pra voltar pra emulação e depois aperte F10 de novo pra voltar ao FuDebug. Você tinha sido um felizardo dos 0,01%!)

   Essa é a configuração do momento, para cada Frame (ou Page, com o emulador chama) qual é slot que está sendo usado. Assim, de 0 a 3FFFh (0 a 16383) temos informações do slot 0 (BIOS), e nos outros 3 frames, de 4000h a FFFFh (16384 a 65535) temos informações do Slot 2 (no caso do Expert e BrMSX, a RAM).

   Assim, se o seu programa estivesse em qualquer área da RAM entre 16384 e 65535 você o encontraria simplesmente procurando com as setar ou usando U XXXX no FuDebug.

   No entanto, existe uma peculiaridade no MSX-DOS: ele sempre carrega um programa a partir do endereço 0100h da RAM. Ora, mas se de 0000h a 3FFFh temos a BIOS, como vamos ver o nosso programa?

   Bem, existe um jeito para fazer isso. O BrMSX tem um comando B (de Break) em que você escolhe uma posição de memória na qual o BrMSX automaticamente abrirá o FuDebug quando ela for executada.

   Vamos fazer exatamente isso agora: Aperte S para voltar ao programa. Ele vai continuar imprimindo "DalPoz é fudeba" na tela. Pressione CTRL+C para parar com isso. Agora, ANTES de executar novamente seu programa, aperte F10 para entrar no FuDebug. No FuDebug, comande:

        B 0100

   O emulador automaticamente voltará para o MSX-DOS. Esse comando que você passou fará com que o FuDebug entre em ação exatamente quando a posição de memória 0100 (o seu programa!) for executada. ( Caso você se pergunte o que aconteceria se alguma coisa na ROM fosse executada no endereço 0100h, leia até o fim da aula, onde eu falo um pouco mais sobre isso. )

   Manda o MSX-DOS executar o seu programa. Instantaneamente o FuDebug vai te mostrar algo mais ou menos assim:

   BrMSX debugger                            Z80                       VDP PSG  
                                             AF=0044  AF'=0082    Reg0  00  55  
   0100> 00           NOP                    BC=00FF  BC'=3CF6    Reg1  F0  00  
   0101  00           NOP                    DE=DDFF  DE'=3CF6    Reg2  00  00  
   0102  00           NOP                    HL=0000  HL'=3CFB    Reg3  00  00  
   0103  11 22 01     LD DE,0122             IX=3EFD              Reg4  01  00  
   0106  CD 1C 01     CALL 011C              IY=3FDB  SZ5H3VNC    Reg5  00  00  
   0109  11 45 01     LD DE,0145             PC=0100  01000100    Reg6  00  00  
   010C  CD 1C 01     CALL 011C              SP=D6FE              Reg7  F1  B8  
   010F  06 05        LD B,05                I=00 EI  IM1 R=5A    Reg8  00  00  
   0111  11 5D 01     LD DE,015D             PPI       MegaROM    Reg9  00  00  
   0114  CD 1C 01     CALL 011C                        0000 00    RegA  00  00  
   0117  10 F8        DJNZ 0111              A=AA      2000 00    RegB  00  0B  
                                             C=5A      4000 00    RegC  00  00  
   Memory                                              6000 01    RegD  00  00  
   0000 C3 03 DE 00 00 C3 06 D7 ........     Page0=2   8000 02    RegE  00  00  
   0008 00 00 00 00 C3 E8 F1 00 ........     Page1=2   A000 03    RegF  00  CF  
   0010 00 00 00 00 C3 EB F1 00 ........     Page2=2   C000 00                  
   0018 00 00 00 00 C3 EE F1 00 ........     Page3=2   E000 00    PSG addr  0E  
   BrMSX settings                                                               
  Resolution: 320x200  Frame skipping: 0001  Bar Graph: OFF  Emulation: NORMAL  
  Joy: -  Sound: ON   VSync: OFF  Session: SINGLE  COM: 1  Video Cache: ON      
  Command:                                                         SCC: OFF     

   Como você pode notar, todos os frames estão no Slot2 agora (RAM). E o ponteiro do BrMSX ( o ">" do lado direito do endereço na seção BrMSX debugger) indica a instrução que será executada em seqüência. E ele está exatamente sobre a posição 0100h, que é o inicio do seu programa! Vamos acompanhar... Existem 3 NOPs aí no começo que são acrescentados pelo assemblador, vamos ver futuramente para que eles servem. A seguir, vem

        LD      DE,0122h

   E você vai pensar... "Poxa isso não tem nada a ver com o

        LD      DE,NOMEDOPRG            ; Indica texto do nome do programa

   Que tinha logo no inicio do meu programa!". Será que não mesmo? O que o FuDebug está mostrando é que estamos "apontando" DE para a posição de memória 0122h. Vamos ver o que tem lá? Digite

        D 0122

   No fudebug. Este comando vai fazer um "Dump" da memória a partir de 0120h, na seção "Memory" do fudebug. Se você fizer isso, vai ver a seguinte tela:

   BrMSX debugger                            Z80                       VDP PSG  
                                             AF=0044  AF'=0082    Reg0  00  55  
   0100> 00           NOP                    BC=00FF  BC'=3CF6    Reg1  F0  00  
   0101  00           NOP                    DE=DDFF  DE'=3CF6    Reg2  00  00  
   0102  00           NOP                    HL=0000  HL'=3CFB    Reg3  00  00  
   0103  11 22 01     LD DE,0122             IX=3EFD              Reg4  01  00  
   0106  CD 1C 01     CALL 011C              IY=3FDB  SZ5H3VNC    Reg5  00  00  
   0109  11 45 01     LD DE,0145             PC=0100  01000100    Reg6  00  00  
   010C  CD 1C 01     CALL 011C              SP=D6FE              Reg7  F1  B8  
   010F  06 05        LD B,05                I=00 EI  IM1 R=5A    Reg8  00  00  
   0111  11 5D 01     LD DE,015D             PPI       MegaROM    Reg9  00  00  
   0114  CD 1C 01     CALL 011C                        0000 00    RegA  00  00  
   0117  10 F8        DJNZ 0111              A=AA      2000 00    RegB  00  0B  
                                             C=5A      4000 00    RegC  00  00  
   Memory                                              6000 01    RegD  00  00  
   0122 50 72 6F 67 72 61 6D 61 Programa     Page0=2   8000 02    RegE  00  00  
   012A 20 34 20 2D 20 42 72 69  4 - Bri     Page1=2   A000 03    RegF  00  CF  
   0132 6E 63 61 6E 64 6F 20 63 ncando c     Page2=2   C000 00                  
   013A 6F 6D 20 6C 6F 6F 70 73 om loops     Page3=2   E000 00    PSG addr  0E  
   BrMSX settings                                                               
  Resolution: 320x200  Frame skipping: 0001  Bar Graph: OFF  Emulation: NORMAL  
  Joy: -  Sound: ON   VSync: OFF  Session: SINGLE  COM: 1  Video Cache: ON      
  Command:                                                         SCC: OFF     
                                                                                

   Olhe lá, na posição 0122h... "Programa 4 - Brincando com loops" ou seja, LD DE,0122h é a codificação exata que o assemblador gerou do seu LD DE,NOMEDOPROG. Uma das principais vantagens do assemblador e de se usar labels (etiquetas) em Assembly é que você não precisa se preocupar mais com "em que endereço isso vai ficar?", porque o assemblador cuida de tudo pra você. Mas você vai precisar ficar esperto ao usar o FuDebug, pois eles vão aparecer com os nomes já trocados para números durante a execução de seu programa. Seguindo essa idéia, o CALL 011Ch deve ser o mesmo que o "CALL MOSTRATXT" de nosso programa. E de fato é! Se você usar:

   U 011C

(Unassemble 011C) vai notar que o seguinte vai aparecer na tela:

   BrMSX debugger                            Z80                       VDP PSG  
                                             AF=0044  AF'=0082    Reg0  00  55  
   011C  0E 09        LD C,09                BC=00FF  BC'=3CF6    Reg1  F0  00  
   011E  CD 05 00     CALL 0005              DE=DDFF  DE'=3CF6    Reg2  00  00  
   0121  C9           RET                    HL=0000  HL'=3CFB    Reg3  00  00  
   0122  50           LD D,B                 IX=3EFD              Reg4  01  00  
   0123  72           LD (HL),D              IY=3FDB  SZ5H3VNC    Reg5  00  00  
   0124  6F           LD L,A                 PC=0100  01000100    Reg6  00  00  
   0125  67           LD H,A                 SP=D6FE              Reg7  F1  B8  
   0126  72           LD (HL),D              I=00 EI  IM1 R=5A    Reg8  00  00  
   0127  61           LD H,C                 PPI       MegaROM    Reg9  00  00  
   0128  6D           LD L,L                           0000 00    RegA  00  00  
   0129  61           LD H,C                 A=AA      2000 00    RegB  00  0B  
                                             C=5A      4000 00    RegC  00  00  
   Memory                                              6000 01    RegD  00  00  
   0122 50 72 6F 67 72 61 6D 61 Programa     Page0=2   8000 02    RegE  00  00  
   012A 20 34 20 2D 20 42 72 69  4 - Bri     Page1=2   A000 03    RegF  00  CF  
   0132 6E 63 61 6E 64 6F 20 63 ncando c     Page2=2   C000 00                  
   013A 6F 6D 20 6C 6F 6F 70 73 om loops     Page3=2   E000 00    PSG addr  0E  
   BrMSX settings                                                               
  Resolution: 320x200  Frame skipping: 0001  Bar Graph: OFF  Emulation: NORMAL  
  Joy: -  Sound: ON   VSync: OFF  Session: SINGLE  COM: 1  Video Cache: ON      
  Command:                                                         SCC: OFF     
                                                                                

   Ora, LD C,09 (STROUT), CALL 0005 (BDOS) e RET é exatamente sua função MOSTRATXT! Então é isso mesmo! Ih, mas e agora pra voltar onde estávamos? Em que posição estava mesmo o marcador do BrMSX?

   Bem, o marcador do BrMSX apenas emula o marcador do próprio Z80. E claro, o Z80 real tem um marcador, afinal, isso é útil pra ele também. Esse marcador é um registrador especial, e chama-se PC (de Program Counter, ou contador de programa) e você pode olhar o valor atual dele na seção Z80, onde você vai encontrar:

        PC=0100

"Ah, é! Era a posição 0100h!"

   Bem, então digite U 0100h pra voltar pra lá... E pumba!

   BrMSX debugger                            Z80                       VDP PSG  
                                             AF=0044  AF'=0082    Reg0  00  55  
   0100> 00           NOP                    BC=00FF  BC'=3CF6    Reg1  F0  00  
   0101  00           NOP                    DE=DDFF  DE'=3CF6    Reg2  00  00  
   0102  00           NOP                    HL=0000  HL'=3CFB    Reg3  00  00  
   0103  11 22 01     LD DE,0122             IX=3EFD              Reg4  01  00  
   0106  CD 1C 01     CALL 011C              IY=3FDB  SZ5H3VNC    Reg5  00  00  
   0109  11 45 01     LD DE,0145             PC=0100  01000100    Reg6  00  00  
   010C  CD 1C 01     CALL 011C              SP=D6FE              Reg7  F1  B8  
   010F  06 05        LD B,05                I=00 EI  IM1 R=5A    Reg8  00  00  
   0111  11 5D 01     LD DE,015D             PPI       MegaROM    Reg9  00  00  
   0114  CD 1C 01     CALL 011C                        0000 00    RegA  00  00  
   0117  10 F8        DJNZ 0111              A=AA      2000 00    RegB  00  0B  
                                             C=5A      4000 00    RegC  00  00  
   Memory                                              6000 01    RegD  00  00  
   0122 50 72 6F 67 72 61 6D 61 Programa     Page0=2   8000 02    RegE  00  00  
   012A 20 34 20 2D 20 42 72 69  4 - Bri     Page1=2   A000 03    RegF  00  CF  
   0132 6E 63 61 6E 64 6F 20 63 ncando c     Page2=2   C000 00                  
   013A 6F 6D 20 6C 6F 6F 70 73 om loops     Page3=2   E000 00    PSG addr  0E  
   BrMSX settings                                                               
  Resolution: 320x200  Frame skipping: 0001  Bar Graph: OFF  Emulation: NORMAL  
  Joy: -  Sound: ON   VSync: OFF  Session: SINGLE  COM: 1  Video Cache: ON      
  Command:                                                         SCC: OFF     
                                                                                

   Voltamos. Tá, tudo bem, mas em que isso ajuda a gente? Simples. Experimente pressionar a tecla F8. Ah! O ponteiro andou pra próxima posição de memória! Sim, mas não só isso. Ele de fato executou a operação (no caso, NOP). Apertando F8 você pode ir passando comando por comando (Step Over). Para acompanhar o que está acontecendo na tela, pressione a tecla 0 que ele vai te mostrar a tela (sem descongelar a emulação). No momento em que a tela de emulação congelada estiver sendo mostrada, qualquer tecla faz voltar ao FuDebug. Assim, pressione 0 para ver que a tela do MSX-DOS continua lá, sem nenhuma alteração. Pressione alguma outra tecla pra voltar ao FuDebug. Pressione F8 até o marcador ficar em frente `a posição de memória 0103h. Nesta posição tem o comando LD DE,0122h. O ponteiro nessa linha indica que ela é a próxima a ser executada. Observe o valor que DE contem atualmente, na seção Z80. No meu caso é DDFFh, mas poderia ser qualquer valor. Pressione F8, executando a instrução LD DE,0122h (e agora o marcador vai apontar para a posição de memória 0106h). Agora você pode olhar que o valor do registrador DE foi mudado para... Exatamente 0122h! Uau! Pressione o F8 novamente para executar o CALL 011Ch. Isso deve ter colocado a mensagem que começa na posição 0122h da RAM na tela... Mas como vemos isso sem descongelar a emulação? Simples... pressione 0. Isso vai te mostrar a imagem com a emulação ainda congelada. Pressione qualquer tecla para voltar. É sempre a mesma coisa. (^= Agora pressione F8 algumas vezes, até que o ponteiro de execução ficar em frente à posição de memória 010Fh. A segunda mensagem já deve estar na tela (você pode conferir com a tecla 0). Da próxima vez que você apertar F8, o emulador vai executar a o comando:

        LD      B,005h

   Que é justamente onde você inicializava o numero de vezes que queria a mensagem. Opa! Tá chegando o lugar onde deve estar o pepino! Pressione F8. B foi carregado com o valor 5. Até aqui tudo dentro do esperado. Pressione F8 novamente. DE deve ter sido carregado com 015Dh, que é o endereço da mensagem fudeba. Pressione F8 novamente. Verifique que a mensagem apareceu na tela, pois o CALL foi executado (use 0 para verificar a tela). Mas ... ei, se você notar por algum motivo estranho B tá valendo 00h! Onde foi parar o meu 5? Bem, agora então não vamos mais usar o F8, e sim o F7. A diferença do F8 para o F7 é que o F8 não entra dentro das funções (por exemplo, usando o F8 você não viu o que acontecia dentro do CALL. Usando o F7 vai poder ver). Assim, aperte F7 e você vai ver que a execução do DJNZ vai fazer tudo aquilo que já tinha dito: subtrair 1 do B (que de 00 passa a FFh, pois em Assembly os números "giram" assim mesmo) e pulou de volta para 0111h! Pressione F7 mais uma vez, e novamente DE será carregado com o valor 015Dh, o endereço da mensagem fudeba. Quando você apertar F7 novamente, vai ver que a execução pula agora para o endereço 011C, ou seja, com o F7 você entrou dentro da função. E o que você acha no endereço 011C? A sua função MOSTRATXT! Que é:

   BrMSX debugger                            Z80                       VDP PSG  
                                             AF=0044  AF'=0082    Reg0  00  55  
   011C> 0E 09        LD C,09                BC=FF02  BC'=3CF6    Reg1  F0  00  
   011E  CD 05 00     CALL 0005              DE=015D  DE'=3CF6    Reg2  00  00  
   0121  C9           RET                    HL=0000  HL'=3CFB    Reg3  00  00  
   0122  50           LD D,B                 IX=3EFD              Reg4  01  00  
   0123  72           LD (HL),D              IY=3FDB  SZ5H3VNC    Reg5  00  00  
   0124  6F           LD L,A                 PC=011C  01000100    Reg6  00  00  
   0125  67           LD H,A                 SP=D6FC              Reg7  F1  B8  
   0126  72           LD (HL),D              I=00 EI  IM1 R=71    Reg8  00  00  
   0127  61           LD H,C                 PPI       MegaROM    Reg9  00  00  
   0128  6D           LD L,L                           0000 00    RegA  00  00  
   0129  61           LD H,C                 A=AA      2000 00    RegB  00  0B  
                                             C=5A      4000 00    RegC  00  00  
   Memory                                              6000 01    RegD  00  00  
   0122 50 72 6F 67 72 61 6D 61 Programa     Page0=2   8000 02    RegE  00  00  
   012A 20 34 20 2D 20 42 72 69  4 - Bri     Page1=2   A000 03    RegF  00  CF  
   0132 6E 63 61 6E 64 6F 20 63 ncando c     Page2=2   C000 00                  
   013A 6F 6D 20 6C 6F 6F 70 73 om loops     Page3=2   E000 00    PSG addr  0E  
   BrMSX settings                                                               
  Resolution: 320x200  Frame skipping: 0001  Bar Graph: OFF  Emulation: NORMAL  
  Joy: -  Sound: ON   VSync: OFF  Session: SINGLE  COM: 1  Video Cache: ON      
  Command:                                                         SCC: OFF     
                                                                                

   Note que B continua com o valor FF. Pressione F7 para executar o LD D,009h, e veja que C efetivamente cai conter esse valor, agora. ATENÇÃO: NÃO USE F7 AGORA! Sempre que houver uma chamada ao BDOS assim (CALL 0005) USE F8! Caso contrario você vai entrar dentro do BDOS e vai ficar maluquinho pra entender o que tá rolando. Antes de apertar F8 e executar o CALL, no entanto, note que B *ainda* vale FFh. Pressione F8. Agora o ponteiro deve estar indicando a posição de memória 0121, pois o CALL já foi executado... porem, note o valor de B agora...

   BrMSX debugger                            Z80                       VDP PSG  
                                             AF=0044  AF'=0082    Reg0  00  55  
   0121> C9           RET                    BC=0002  BC'=3CF6    Reg1  F0  00  
   0122  50           LD D,B                 DE=0175  DE'=3CF6    Reg2  00  00  
   0123  72           LD (HL),D              HL=0000  HL'=3CFB    Reg3  00  00  
   0124  6F           LD L,A                 IX=3EFD              Reg4  01  00  
   0125  67           LD H,A                 IY=3FDB  SZ5H3VNC    Reg5  00  00  
   0126  72           LD (HL),D              PC=0121  01000100    Reg6  00  00  
   0127  61           LD H,C                 SP=D6FC              Reg7  F1  B8  
   0128  6D           LD L,L                 I=00 EI  IM1 R=6D    Reg8  00  00  
   0129  61           LD H,C                 PPI       MegaROM    Reg9  00  00  
   012A  20 34        JR NZ,0160                       0000 00    RegA  00  00  
   012C  20 2D        JR NZ,015B             A=AA      2000 00    RegB  00  0B  
                                             C=5A      4000 00    RegC  00  00  
   Memory                                              6000 01    RegD  00  00  
   0122 50 72 6F 67 72 61 6D 61 Programa     Page0=2   8000 02    RegE  00  00  
   012A 20 34 20 2D 20 42 72 69  4 - Bri     Page1=2   A000 03    RegF  00  CF  
   0132 6E 63 61 6E 64 6F 20 63 ncando c     Page2=2   C000 00                  
   013A 6F 6D 20 6C 6F 6F 70 73 om loops     Page3=2   E000 00    PSG addr  0E  
   BrMSX settings                                                               
  Resolution: 320x200  Frame skipping: 0001  Bar Graph: OFF  Emulation: NORMAL  
  Joy: -  Sound: ON   VSync: OFF  Session: SINGLE  COM: 1  Video Cache: ON      
  Command:                                                         SCC: OFF     
                                                                                

   Voltou para zero! Uau! Então o vilão da nossa historia é esse "CALL BDOS"?!? Sim, mais ou menos isso. A chamada da função STROUT (9) do BDOS não preserva o valor do registrador B. Isso faz com que nosso contador fique zoado!

   Bem, agora já achamos o Bug... voltemos à programação normal para tentar corrigi-lo...

   Corrigindo o Bug

   Bem, então o problema é que precisamos "guardar" o contador em algum lugar seguro antes de chamar a função do BDOS. Poderíamos colocar o valor em um outro registrador, mas quem sabe qual deles é seguro? Como essa aula é pesada, não vou introduzir novos conceitos. Vamos corrigir essa falha da mesma forma que corrigimos quando descobrimos que perdíamos o valor de E após coletarmos o mesmo com o CONIN, numa das aula anteriores: salvando na memória.

   Assim, a nossa funçãozinha:

        LD      B,5                     ; Indica repetição de 5 vezes.
LOOP:   LD      DE,FUDEBA               ; Indica texto fudeba
        CALL    MOSTRATXT               ; Mostra texto
        DJNZ    LOOP                    ; Repete os comandos LD DE,FUDEBA e CALL MOSTRATXT

Fica:

        LD      B,5                     ; Indica repetição de 5 vezes.
LOOP:   LD      DE,FUDEBA               ; Indica texto fudeba
        LD      A,B                     ; Copia em A o contador 
        LD      (VAR1),A                ; Grava o valor do contador na MEMORIA.
        CALL    MOSTRATXT               ; Mostra texto
        LD      A,(VAR1)                ; Copia para A o conteúdo de VAR1
        LD      B,A                     ; Coloca de volta no contador
        DJNZ    LOOP                    ; Repete os comandos LD DE,FUDEBA e CALL MOSTRATXT
                                        ; Decrementando B até ele ser zero.

   Lembrando de acrescentar a VAR1 de volta na lista de variáveis, no fim do programa com:

VAR1:   DB      000h

   O programa final fica:

--- Cortar Aqui ---
BDOS    EQU     5

STROUT  EQU     9

START:
        ; Mostra informações do programa e faz pergunta
        LD      DE,NOMEDOPRG            ; Indica texto do nome do programa
        CALL    MOSTRATXT               ; Mostra texto
        LD      DE,AUTOR                ; Indica texto do nome do autor
        CALL    MOSTRATXT               ; Mostra texto

        LD      B,5                     ; Indica repetição de 5 vezes.
LOOP:   LD      DE,FUDEBA               ; Indica texto fudeba
        LD      A,B                     ; Copia em A o contador 
        LD      (VAR1),A                ; Grava o valor do contador na MEMORIA.
        CALL    MOSTRATXT               ; Mostra texto
        LD      A,(VAR1)                ; Copia para A o conteúdo de VAR1
        LD      B,A                     ; Coloca de volta no contador
        DJNZ    LOOP                    ; Repete os comandos LD DE,FUDEBA e CALL
MOSTRATXT

        JP      0                       ; Volta ao MSX-DOS


;------
; MOSTRATXT - Função que mostra um texto cuja seqüência é terminada por '$'.
;    Entrada: DE - Aponta para seqüência a ser mostrada, terminada por '$'
;------
MOSTRATXT:
        LD      C,STROUT                ; Indica função de mostrar texto do BDOS
        CALL    BDOS                    ; Manda o BDOS executar.
        RET                             ; Retorna

NOMEDOPRG:      DB      'Programa 4 - Brincando com loops',13,10,'$'
AUTOR:          DB      '  Por Daniel Caetano',13,10,10,'$'
FUDEBA:         DB      'O DalPoz é um fudeba!',13,10,'$'
VAR1:   DB      000h

        END
--- Cortar Aqui ---

   Que ao ser compilado e executado mostrará direitinho a mensagem 5 vezes.

   Na próxima aula aprenderemos a mexer com alguns outros recursos do Z80, como a PILHA, e também introduziremos alguns novos conceitos... Aguardem.

  Um pouco mais sobre o FuDebug

   Se você ficou curioso lá em cima, com o fato de ter usado o comando B 0100 e o MSX-DOS continuar funcionando normalmente, inclusive com seus comandos, e o BrMSX só' entrou quando o programinha foi executado, saiba que isso não é magica não. Na verdade, isso só ocorre porque o MSX-DOS não tem NADA de sua estrutura na região 0100h. E também não chama nenhuma função de BIOS no endereço 0100h. Caso essas duas condições não se verificassem, talvez ele pudesse parar num endereço 0100h que não fosse o seu programa (fosse a posição 0100h de algum outro slot que não o da memória). Principalmente no futuro, quando você muitas vezes usara o comando B (break) com endereços totalmente diferentes de 0100h (para parar direto na posição 0109h, por exemplo). Bem você precisa ficar esperto para perceber isso. Um bom indicador são os valores dos "PAGE0" a "PAGE3" da seção da PPI. Como seu programa está na RAM, se o endereço que você mandou parar estiver indicado como sendo um frame que não é da RAM (0 ou 1, por exemplo) com toda a certeza do mundo isso não será um trecho do seu programa. Conhecer bem seu programa também ajuda nessas horas. Assim, se parar no endereço que você queria, mas o conteúdo não é o que você esperava, aja simples: pressione F7 para ele pular para o próximo endereço e use novamente o comando B (break) indicando o mesmo endereço que havia dado anteriormente. Em geral isso resolve.

   Algumas palavras finais...

   Povo,

   Sei que esta aula é pesada, e que o FuDebug pode parecer meio confuso no começo. Por ser poderoso, acaba sendo um pouco complexo mexer com ele também. No entanto, com ele a programação fica centenas de vezes mais simples...! Eu não mostrei nem 5% da capacidade dele. Com o tempo vamos conhecendo mais. É essencial que vocês "percam tempo" mexendo com ele, e fiquem craques. "defeitos" como esse que mostrei no ultimo programa acontecem aos montes em programas assembly mais complicados, e identificar na mão muitas vezes não é possível, como nesse caso! Essa aula foi dividida em varias partes, e todas elas ficaram enormes (ainda não preparei as outras, mas imagino o que vou colocar nelas) mas é agora que a coisa começa a andar, e coisas úteis começam a ser construídas. Espero que o tempo que gastei bolando muita coisa que está aqui (meses) e o tempo que gastei escrevendo essa aula (muitas e muitas horas, mesmo!). E o que posso dizer é que estou tentando fazer a minha parte, mas consultar outros livros é essencial a aprender a programar ASM. Com o pouco que eu passei, já é possível pegar a lógica de como o assemblador funciona e, lendo um bom livro de Assembly Z80 e tendo à mão um MSX2 Technical Handbook já dá até pra ir embora sozinho... de modo que eu até pretendo dar continuidade no curso, mas adianto que com preguiça não se vai a lugar algum em ASM, porque os códigos são, costumeiramente, enormes e muito complexos, e demandam um bom tempo de tentativa e erro para aprender a lidar com as dificuldades mais comuns.

   O meu desafio é: quero ver alguém que consiga fazer algo interessante com o que eu já passei até essa aula. Estou a disposição para responder duvidas e ajudar com alguma coisa, mas assembly é o tipo da coisa que só' praticando pra aprender. Ninguém aprende só lendo.

  Um abarco e espero que esse curso, embora meio "quebrado" por períodos de estiagem, umedeça a mente de vocês, para que novas idéias possam germinar e ganhar vida... (pô, ficou bonito isso!)


  Abraços,

Daniel Caetano.

PS: Sugestões e comentários são bem-vindos. (^=