terça-feira, maio 09, 2023

MSX: Compass

O Compass é um ótimo assembler/debuger feito para o MSX pelo grupo Compjoetania TNG, maiores informações sobre o que ele faz e como adquirir, somente com o grupo, infelizmente, na minha última pesquisa, o site deles estava fora do ar.

Aqui vai um pequeno manual de referência básica de operação do mesmo.


Introdução

O disco de instalação, possui os arquivos do Compass, os arquivos do MemMan e arquivos de documentação, estes arquivos são muito interessantes, pois contém muita informação técnica sobre o MSX, além do manual detalhado do Compass, estes arquivos estão compactados no formato .PMA (o PMEXT está incluso no disco). No meu caso eu instalei tudo no meu Turbo-R com IDE e HD, entao criei um diretório para o necessário para executar o compass e o memman, e sob ele, um outro para a documentação de tudo. Para trabalhar em disco, o ideal é extrair num disco (que contenha o DOS, já que o mesmo não está incluso) os arquivos de execução, e em outros dois discos os arquivos de documentação e exemplos.

Disco 1 compass.com

  • compass.dat
  • bk.com
  • cfgmman.com
  • memman.com
  • tk.com
  • tl.com
  • tv.com
  • memman.bin
  • command.com
  • command2.com
  • msxdos.sys
  • msxdos2.sys
Disco 2 disk_rom.txt
  • c12manua.txt
  • diskvari.txt
  • dos2var.txt
  • hoe-rel.txt
  • io_poort.txt
  • mathpack.txt
  • msxdos_1.txt
  • msxdos_2.txt
  • msxhooks.txt
  • systemvr.txt
  • bios.txt
Disco 3(disco 2 se não descompactado)
  • turbor.doc
  • mm24spec.doc
  • bk104man.txt
  • caps.tsr
  • color.tsr
  • mm24intr.doc
  • turbor-doc
  • compassv.txt

Para carregar o compass, basta executar o “compass” a partir do DOS, caso queira, pode passar como parametro um nome de arquivo (“compass SAMPLE.ASM” e o mesmo será carregado no buffer #1), o mesmo exige um MSX 2 ou superior, com, pelo menos, 128Kb de memória mapeada, embora 256k seja o recomendado (interna, externa ou combinada, mas outro tipo de memória não é permitido), e uma das seguintes combinações, na ordem da melhor para a pior configuração:

  1. DOS2+Memman
  2. DOS2
  3. DOS1
  4. DOS1+Memman (esta listada por último por ser uma configuração que costuma dar problemas)

O programa é executado em Screen 0, 80 colunas por 26.5 linhas e 4 cores, sendo que, além da memória mapeada,  uma parte da VRAM também é utilizada (de #0000 a #7FFF) e dependendo da configuração, uma série de features são suportadas:

Rodando sob MSX-DOS 2, os serviços de sub-diretórios estão plenamente disponíveis, além da RAM DISK.

Com Memory Mapper disponível, o programa pode combiná-las e suporta até 4 buffers de 256Kb cada.

Sob o Turbo-R, pode executar o programa nos modos Z-80, R800 ROM e R800 RAM
Funciona bem quando instalado em Hard Disk, basta manter o “compass.com” e o “compass.dat” no mesmo diretório

Ao iniciar o Compass, após o logo, o programa fará um checkup do hardware instalado, levantando quantidade de memória, gerenciador de memória, etc.. São necessários, pelo menos, 5 páginas livres das mappers instaladas, sendo que, 2 devem estar livres na mapper primária e 4 não podem estar segmentadas na TPA, se as condições estiverem satisfatórias, o Compass aloca no máximo 1536Kb de memória, não permitindo que outros programas a usem.

Os menus podem ser acessados usando as teclas [F1] a [F5], basta seguir a ordem da tela, para sair dos mesmo, basta dar [ESC]. O programa tem suporte a mouse e a teclas aceleradoras, que serão listadas na sequência. Duas combinações de tecla importantes são [Ctrl]+[Q] para encerrar o sistema e [Shift]+[ESC] para sair para o shell DOS ou Basic, dependendo do caso, você pode teclar a combinação para cair para o DOS inicialmente, comandar BASIC e ir ao basic para testar alguma rotina, estando no BASIC, basta teclar novamente a combinação e volta ao ponto que estava no Compass, pressionando mais uma vez, cai no BASIC novamente.

O objetivo desta entrada, não é traduzir o manual, que já é excelente, aqui vai servir apenas como uma referência a qual eu possa consultar sempre que precisar de algum detalhe sobre o programa.

Atalhos de Teclado

Uma das maiores vantagens do Compass, está em suas teclas de atalho muito bem planejadas, ganha-se muito em velocidade com elas.

Teclas Gerais

  • Japan NO: Modo Z-80
  • Japan YES: Moro R800-ROM
  • [Ctrl]+C: Calculadora
  • [Ctrl]+D: Menu de disco
  • [Ctrl]+Q: Encerra o programa
  • [Shift]+[ESC]: Shell para o DOS ou BASIC

Teclas do Módulo Assembler

  • [Ctrl]+A: Assembla o fonte do buffer corrente na memória
  • [Ctrl]+E: Marca o fim do bloco
  • [Ctrl]+G: Executa a posição de memória indicada (Roda programa)
  • [Ctrl]+J: Vai para uma determinada linha no buffer
  • [Ctrl]+K: Copia o bloco marcado para a linha corrente
  • [Ctrl]+L: Copia o label do bloco para a linha corrente
  • [Ctrl]+N: Continua para a próxima busca
  • [Ctrl]+P: Imprime o bloco selecionado
  • [Ctrl]+R: Mostra os erros da última compilação
  • [Ctrl]+S: Marca o início do bloco
  • [Ctrl]+T: Desmarca o bloco
  • [Ctrl]+V: Move o bloco para a linha corrente
  • [Ctrl]+W: Exclui o bloco
  • [Ctrl]+Z: Busca/Troca o texto
  • [Ctrl]+[n]: Muda para o Buffer indicado por [n], [n] pode ser 1,2,3 ou 4
  • [Ctrl]+5: Seleciona o modo Pal (50 Mhz)
  • [Ctrl]+6: Seleciona o modo NSTC (60 Mhz)
  • [Ctrl]+[Fn]: Armazena a posição corrente, [Fn] pode ser [F1],[F2],[F3],[F4] ou [F5]
  • [Shift]+[Fn]: Pula para a posição armazenada por [Ctrl]+[Fn], [Fn] pode ser [F1],[F2],[F3],[F4] ou [F5]
  • [Ctrl]+[INS]:  Insere uma linha
  • [Shift]+[INS]: Insere 10 linhas
  • [Ctrl]+[DEL]: Remove uma linha
  • [Shift]+[DEL]: Remove da posição corrente até o final da linha
  • [HOME]: Vai para o início ou fim do buffer
  • [GRAPH]+Cursores: Troca Maiúscula –> para Minúscula <-
  • [Ctrl]+[UP] e [Ctrl]+[DOWN]: Rola a tela pra cima ou para baixo
  • [Ctrl]+[LEFT] e [Ctrl]+[RIGHT]: Para o inicio da próxima palavra ou da anterior
  • [Shift]+[UP] e [Shift]+[DOWN]: Rola 100 linhas para cima ou para baixo
  • [Shift]+[RIGHT] e [Shift]+[Left]: Vai para o inicio ou final da linha
  • [STOP]: Vai para o modo MONITOR

Teclas do Módulo Monitor

  • [Ctrl]+A: Move o monitor para o endereço desejado
  • [Ctrl]+E: Dá  um PEEK em um endereço qualquer
  • [Ctrl]+F: Preenche um bloco de memória com um valor
  • [Ctrl]+K: Copia um bloco de memória
  • [Ctrl]+N: Continua a próxima busca
  • [Ctrl]+O: Dá um POKE em um endereço qualquer
  • [Ctrl]+P: Imprime um bloco de memória
  • [Ctrl]+X: Muda o modo de link com o Debugger
  • [Ctrl]+Z: Busca
  • [Ctrl]+[UP] e [Ctrl]+[DOWN]: Rola uma tela pra cima ou pra baixo
  • [STOP]: Vai para o módulo DEBUGGER
  • [SELECT]: Troca entre os módulos DEBUGGER e MONITOR

Teclas do Módulo Debugger

  • [Ctrl]+[UP] e [Ctrl]+[DOWN]: Rola exatamente 1 byte para trás ou para frente
  • [Ctrl]+A: Move o debugger para o endereço
  • [Ctrl]+B: Seta um breakpoint
  • [Ctrl]+E: Executa até o próximo breakpoint
  • [Ctrl]+H: Coloca o program counter na posição do cursor
  • [Ctrl]+I: Coloca o registro SP no seu valor inicial
  • [Ctrl]+J: Coloca o endereço do cursor no program counter
  • [Ctrl]+L: Muda o modo de link do mini-monitor
  • [Ctrl]+P: Muda a seleção corrente dos slots
  • [Ctrl]+R: Altera os registradores
  • [Ctrl]+S: Passo
  • [Ctrl]+T: Traça
  • [Ctrl]+U: Vai para o endereço armazenado pela opção TEMPORARY
  • [Ctrl]+V: Mostra os breakpoints
  • [Ctrl]+W: Apaga os breakpoints
  • [Ctrl]+Y: Traça especial
  • [STOP]: Vai para o módulo Assembler
  • [SELECT]: Troca entre os módulos DEBUGGER e MONITOR
  • [Shift]+[UP] e [Shift]+[DOWN]: Salta aproximadamente 200 bytes para trás ou para frente

Palavras Reservadas

Palavras reservados do Compass, que não podem ser usadas como labels/instruções.

Comandos

  • ADC    
  • CPI    
  • EXX    
  • JP     
  • NEG    
  • PUSH   
  • RLD    
  • SET
  • ADD    
  • CPIR   
  • HALT   
  • JR     
  • NOP    
  • RES    
  • RR     
  • SLA
  • AND    
  • CPL    
  • IM     
  • LD     
  • OR     
  • RET    
  • RRA    
  • SLL
  • BIT    
  • DAA    
  • IN     
  • LDD    
  • OTDR   
  • RETI   
  • RRC    
  • SRA
  • CALL   
  • DEC    
  • INC    
  • LDDR   
  • OTIR   
  • RETN   
  • RRCA   
  • SRL
  • CCF    
  • DI     
  • IND    
  • LDI    
  • OUT    
  • RL     
  • RRD    
  • SUB
  • CP     
  • DJNZ   
  • INDR   
  • LDIR   
  • OUTD   
  • RLA    
  • RST    
  • XOR
  • CPD    
  • EI     
  • INI    
  • MULUB  
  • OUTI   
  • RLC    
  • SBF
  • CPDR   
  • EX     
  • INIR   
  • MULUW  
  • POP    
  • RLCA   
  • SCF

Operandos

  • A      
  • H      
  • AF     
  • IXH    
  • C      
  • PE
  • B      
  • I      
  • BC     
  • IXL    
  • M      
  • PO
  • C      
  • L      
  • DE     
  • IY     
  • NC     
  • Z
  • D      
  • R      
  • HL     
  • IYH    
  • NZ
  • E      
  • SP     
  • IX     
  • IYL    
  • P

Diretivas

  • ASEG   
  • DEFW/DW
  • INCLUDE
  • BREAKP
  • END    
  • .LABEL
  • COND   
  • ENDC   
  • MACRO
  • CSEG   
  • ENDIF  
  • ORG
  • DEFB/DB
  • ENDM   
  • PHASE
  • DEFC/DC
  • EQU   
  • PUBLIC
  • DEFM/DM
  • EXTRN  
  • TSRHOOKS
  • DEFL   
  • IF     
  • UPPER

Mensagens de Erro

Algumas das mensagens de erro do Compass

Mensagens do Editor

  • Databuffer to small: O programa não consegue carregar ou editar um fonte pois o databuffer não é suficiente, você pode tentar mudar isso no menu “Memory”
  • Destination in block: Mover ou copiar um bloco com o cursor ainda dentro do mesmo
  • No block selected: Tentativa de executar um comando de bloco sem ter o bloco selecionado
  • Printer not ready: Impressora não conectada, offline ou com problema
  • Sourcebuffer to small: O programa não consegue carregar ou editar um fonte pois o sourcebuffer não é suficiente, você pode tentar mudar isso no menu “Memory”

Erros do Assemblador

  • Bad instruction: O compass não pode reconhecer o comando
  • Bad mnemonic: Os registros, labels, valores, etc. nao foram reconhecidos
  • Divizion by zero: Tentativa de dividir um número (representado por um label) por zero
  • Illegal symbol in label: Tentativa de criar um label com caracter inválido
  • Label não definido: Tentativa de  usar um label que ainda não foi definido até este ponto
  • Label too long: Nome de label maior do que o especificado na configuração (INSTALLATIONS) ou pela diretiva (.LABEL)
  • Labelbuffer too small: Durante a montagem, o labelbuffer foi sobrecarregado, você pode tentar mudar isso no menu “Memory”
  • Macro already opened: Você disparou uma macro enquanto estava na definição da macro
  • Macro not definied: Usando o comando MACRO sem nomea-la corretamente
  • Macro not opened: Tentativa de encerrar uma MACRO com ENDM sem efetivamente ter iniciado a definição da mesma
  • Macro used as label: Tentativa de usar um nome de MACRO como LABEL
  • Missing “)”: A expressão informada não tem seus parenteses balanceados
  • Number out of range: O número excede o limite da operação, exemplo, LD a,300
  • Offset out of range: O endereço de destinho não pode ser alcançado
  • Phase still active: Tentativa de usar ORG / CSEG / DSEG / ASEG quando ainda se encontra no modo PHASE.
  • Public not found: Os labels públicos não se encontram no módulo corrente
  • Redefined label: O label definido já foi definido anteriormente
  • Relocateable instruction: Uso de uma instrução relacionada a programas relocáveis na montagem de um programa não relocável
  • Too many if’s: Número máximo de IF’s aninhados foi ultrapassado (16)

Erros do Monitor

  • Not equal: As áreas de memórias sendo comparadas não são iguais
  • Printer not ready: Impressora não conectada, offline ou com problema
  • String not found: A string informada não pode ser encontrada no bloco de memória selecionado

Erros do Debugger

  • Breakpoint memory filled: A memória disponível para breakpoints está cheia
  • Call buffer already empty: Tentativa de recuperar um endereço do buffer de chamadas, mas o mesmo está vazio
  • Call buffer already filled: Tentativa de armazenar um endereço no buffer de chamadas, mas o mesmo está cheio
  • Printer not ready: Impressora não conectada, offline ou com problema
  • There are no breakpoints to delete: Tentativa de excluir um breakpoint, mas a lista está vazia
  • There is no breakpoint at that address: Tentativa de excluir um breakpoint para um endereço mas o mesmo não existe
  • This address is already defined as breakpoint: O endereço informado como breakpoint já foi definido anteriormente
  • You haven’t defined any breakpoints: Tentativa de executar um programa até um breakpoint, mas não existem breakpoints definidos

Erros de Disco

  • Disk I/O error: O disco não pode ser lido ou gravado
  • Disk off-line: Não existe disco na unidade ou o mesmo não está formatado
  • File not found: O nome do arquivo ou caminho informado não pode ser encontrado
  • No assembler file: Tentativa de abrir um arquivo como sendo fonte, mas o mesmo não é um fonte assembly (.ASM)
  • No binary file: Tentativa de abrir um arquivo como sendo binário mas o mesmo não é binário
  • No diskdrive: Tentativa de gravar um setor no disco rigido, a operação não é permitida
  • Write error: Erro durante a escrita, tente com outro disco ou verifique se o disco não está cheio
  • Write protected: O disco que a operação de escrita está sendo executada, está protegido contra gravações

Módulo Assembler

Descrição das principais funções do módulo assembler

No menu System->Disk temos o acesso ao gerenciador de arquivos do Compass, aproveito aqui para descrever como operar o mesmo:

  • Para escrever um nome de arquivo, basta começar a digitar, o programa reconhece a ação e já muda o foco para o campo Filename, caso pressione [ESC] o nome digitado é apagado e o antigo nome é re-escrito.
  • O campo backup pode ser alterado com as teclas [CTRL]+B, e pode ser off, ou seja, sem backup ao salvar arqvuios, ASM, que ao salvar um arquivo ASM existente, ele cria um backup com a versão anterior na extensão .BAK, e ASCII que faz o mesmo para arquivos TXT puros.
  • O campo type é alterado com [CTRL]+T: ASM –>Arquivo fonte assembly (otimizados), ASCII->Arquivo texto puro, Binary->Arquivo binário contendo regiões da memória, Data->Arquivos de dados sem header, Block->Arquivos texto mas ligados a seleção de bloco de texto, Sector->Setores de disco para edição (não funciona com HD).
  • O sourcebuffer indica sobre qual buffer será feita a operação de disco, e pode ser alterado com [Ctrl]+n, onde n pode ser 1,2,3 ou 4.
  • [ESC] encerra o modo disco, e volta ao módulo que o invocou.
  • As opções Save, Load, Dir, Type, Mkdir, Kill e Format, são auto explicativas e podem ser selcionadas usando as teclas cursoras. Dir aceita parametro (campo Pathname) onde pode informar o disco, o caminho e uma mascara para mostrar o diretório, apois dar enter, a seleção é mostrada e com as setas navega-se, usando o [RETURN] para executar a operação selecionada.

No menu Installations->Sourcebuffer, podemos escolher o buffer ativo na tela, pressionando [RETURN] em cima da opção.

Intallations->CPU permite mudar o modo de CPU do Turbo-R do mesmo modo.

Installations->Label define o tamanho dos labels, [RETURN] para ativar a mudança e setas cursoras para aumetar ou diminuir.

Installations->ret inset, auto align e upper case, indicam se uma linha sera criada a cada enter, e se a mesma vai ser alinhada automaticamente, e se o montador vai diferenciar maiúsculas de minúsculas, basta mudar de on para off pressionando [RETURN].

Options->Show errors, mostra  uma lista dos erros de montagem, dando enter na mensagem, te leva para a linha com erro.

Options->Label faz o mesmo para os labels definidos.

Labels

Podem ter seu tamanho variando entre 6 e 20, mas precisam ser definidos no menu de configuração, ou na diretiva .LABEL.

Podem ter os seguintes caracteres: ABCDEFGHIJKLMNOPQRSTUVWXYZ, abcdefghijklmnopqrstuvwxyz, 0123456789_-!?.

Não podem iniciar com um dígito.

Não é permitido o uso de palavras reservadas.

Não são necessários “:” após o label ser definido.

Usar “::” após o label, transforma o mesmo em público.

Comandos especiais

  • PUSH reg1, reg2, reg3, … ; Será compilado como instruções push separadas.
  • POP reg1, reg2, reg3,… ; Idem.
  • Operações que envolvem o registrador A, podem omitir o mesmo, exemplo, LD A,#41, pode ser escrito como LD #41.
  • EX AF,AF ; Suportado apenas por compatibilidade.
  • LD A,”” ; Identico a LD A,0.
  • LD HL,”KL” ; Identico a LD HL,#4B4C.
  • LD B ; Identico a LD A,B, pode ser usado para todas as instruções que usam o registro A.
  • DJNZ $ – 2 ; O dolar representa o endereço corrente.
  • LD A, %11 01 11 10 ; Espaços são permitidos em binários.
  • MULUB a,b ; Multiplicação, resultado de 16 bits em HL (c,d,e também suportados).
  • MULUW hl,bc ; Multiplicação, resultado de 32 bits em DE-HL (SP também suportado).

Diretivas usadas pelo Compass

  • ORG #0000: Endereço inicial de compilação, se não usado, o Compass assume #100.
  • label EQU #00: Define constantes.
  • END: Usado para encerrar a compilação, não é obrigatório, mas pode ser usado quando você quer compilar apenas uma parte do programa.
  • DEFB / DB / DEFM / DM: Pokear valor no endereço corrente (ex: DB “Teste de impressão”,0).
  • DEFC / DC : Idem ao DB mas o bit 7 do último valor e setado, podendo ser usado para verificar final de string.
  • DEFS / DS n [,f]: Para criar blocos de tamanho “n” vazios ou preenchidos com algum valor “f”.
  • DEFW / DW: Idem ao DB mas define valores de 16 bits.
  • TSRHOOKS: Necessário na frente dos hooks usados pelo TSR, mais sobre ela na parte de TSRs.
  • .LABEL l: Define o tamanho dos labels a partir da diretiva em “l”.
  • .UPPER on/off: Define se o compilador deve ser sensível ou não à caixa dos labels/constantes.
  • BREAKP: Marca o endereço corrente como um breakpoint.
  • INCLUDE b [,f]: Adiciona fontes externas ao fonte corrente, o arquivo deve estar carregado em um buffer “b”, caso use como parametro um arquivo “f”, o mesmo será carregado no buffer “b” antes.
  • MACRO / ENDM / DEFL: Diretivas usadas na definição de macros, mais sobre elas na parte referente a macros.
  • IF / COND / ELSE / ENDIF / ENDC: Diretivas usadas na compilação condicional, mais sobre isso em sua parte pertinente.
  • CSEG / DSEG / ASEG / PUBLIC / EXTRN / .PHASE / .DEPHASE: Diretivas usadas na criação de arquivos relocáveis, mais na parte sobre os mesmos.

O Compass gera, por padrão, arquivos .COM, com o inicio em #100, mas pode ser capaz de gerar aquivos .BIN para serem carregados pelo BASIC com bload, para isso, basta criar seu programa com a mascara a seguir:

defb #fe                ;Tipo de arquivo (binario)
defw inicio             ;Endereco de inicio
defw fim                ;Endereco final do bloco
defw inicio             ;Endereco de execucao (bload,r)
        org #c000       ;Endereco da compilacao
inicio
        ld a,0          ;Seu programa inicia aqui
        ret
fim equ $               ;Marca o endereco final

Após compilar, vai ter um programa que inicia em &HC000, e pode ser carregado com bload “programa.bin”, s . Não esquecer de mudar o nome do arquivo, pois como padrão ele usa noname.com.

Módulo Monitor

O monitor do Compass roda totalmente em tempo real, ou seja, as informações estão sempre sendo atualizadas na tela, para trocar do modo Hexa para o ASCII, basta usar a tecla [TAB], para alterar os valores, basta ir digitando os mesmos, pressionando [ESC], no modo hexa, quando entra apenas o primeiro dígito, o valor anterior e resetado, e usando a tecla [SELECT] da pra mudar rápidamente do módulo Monitor para o Debugger.

As opções dos menus são auto-explicativas, mas uma merece algum esclarecimento. Installations->Chaining, pressionando [RETURN] nesta opção, você troca o modo de ligação entre o monitor e o debugger, ou seja, o endereçamento do monitor vai sendo refletido com algum do debugger, dependendo de qual opção foi escolhida, “minimonitor”, “registro pc” ou “cursor”.

Calculadora

Uma dica legal, que pode ser usada em todos os módulos, é chamar a calculadora, a calculadora do Compass e bem completa e no monitor, as vezes quebra um galho poder ter um método de converter ou calcular algum número.

Algumas caracteristicas da calculadora do compass:

  • Usa a mesma prioridade de calculo do Basic e permite o uso de parenteses infinitos para mudar a peioridade da expressão
  • Multiplos sinais de “-” podem ser usados, fazendo com que —5 se transforme em -5 e –5 em 5.
  • Podem ser usados operadores lógicos (isso é poderoso) AND, OR, XOR e MOD
  • O resultado da operação anterior pode ser usado na próxima, basta usar o simbolo “$”,algo como $-2
  • Após a compilação prévia, podem ser usados os labels do programa nas expressões, algo como (DATA-START)/1024+ENDPROG
  • Vale lembrar que o resultado da conta é apresentado de várias maneiras, facilitando o uso do mesmo

Pesquisa/Fill

A pesquisa, de valores também oferece um suporte bem adequado, informando “TESTE” ele procura ‘T’,’E’,’S’,’T’,’E’, mas pode informar algo mais complexo, como “ZOEK”,0,label que procura por ‘Z’,’O’,’E’,’K’,0,label.

A opção Fill também tem uma particulariedade, se voce informar um valor maior de 255, o fill vai preencher o bloco com um número de 16 bits, caso o valor seja entre 0 e 255, o fill vai perguntar se deve ser tratado como 8 ou 16 bits (Peek e Poke trabalham da mesma maneira).

Módulo Debugger

Uma das características mais legais do debugger do Compass, e o mini-monitor, um pequeno monitor que permite examinar um bloco de memória enquanto você depura o programa, este módulo ainda pode ser linkado com o debugger, do mesmo modo que a ligação do monitor, mas apenas com as opções “registro PC” e “cursor” (basta mudar na opção Installations->Linking).

Outra opção legal e a Installations->MSX rst, que pode receber yes ou no, bastando dar [RETURN] nela, onde as instruções RST serão mostradas como na BIOS.

RST 30 DB 00;578A        F7008A57

Ao invés de:

RST 30       F7
NOP          00
ADC A,C      8A
LD D,A       57

O que ajuda no desenvolvimento de sua própria BIOS. Outra coisa bacana do Compass e que algumas instruções são monitoradas para evitar alguns travamentos ou corrompimento da tela, isso além de ter um abiente separado para o debugger e para o programa, ou seja, cada um tem seu Stack, Registros, Memória, Interrupção e seleção de slots preservado a cada troca de ambiente entre a simulação da execução e o debugger em sí. Outras instruções críticas podem ser monitoradas para segurança, por exemplo, os portos do VDP (mais sobre isso abaixo), e no caso de desabilitar as interrupções, e comandar um HALT, um aviso será disparado, pois caso a instrução seja executada, o MSX irá travar. Instruções de gerenciamento de memória também são monitoradas, ou seja, escrita e leitura nos portos #A8, #FF, #FE, #FD, #FC e o registro de seleção de slots #FFFF são gerenciados pelo próprio gerenciador de memória do Compass (com excessão das instruções INIR, INDR, INI e IND). No caso do registro de slots, as seguintes instruções são monitoradas:

  • LD reg,(HL)
  • LD (HL),reg
  • LD (HL),value
  • LD A,(#FFFF)
  • LD (#FFFF),A

Obviamente que se algum método não convencional for usado, o Compass não tem como identificar.

O debugger tem 2 ponteiros, um, chamado cursor, que pode navegar por todo o programa, sem alterar o outro, que representa o “PC”, ou seja, você pode navegar pelo programa livremente sem efetivamente executar as instruções, a tecla [H] faz o PC se mudar para o cursor “>” e a tecla [J] faz o inverso, ou seja, faz o cursor se mudar para o PC.

As opções são auto explicativas, mas algumas merecem atenção.

Options->Register permite alterar os registradores, ao selecioná-la, um cursor e mostrado na área de registradores, você seleciona o mesmo com as setas e usa a barra de espaço para entrar no modo de edição, o legal é que pode-se usar um label, ou um calculo para o valor do registro (função calculadora), as flags e a indicação DI/EI também podem ser alteradas, embora o registro IR não.

Options->Temporary e Options->Return são uma mão na roda, ao escolher a primeira, será solicitado um endereço, e o cursor e desviado para tal local, quando finalizar a inspeção, basta usar a Return para voltar no local que o cursor estava antes da operação.

Options->Dis>Source gera  uma listagem desassemblada do intervalo de memória solicitado no buffer de edição corrente, apagando o que se encontrava lá antes, claro.

I/O List->insert e I/O List->delete, serve para incluir ou excluir portas que devem ser protegidas na execução/depuração do programa, algumas das principais portas já estão listada e podem ser excluídas e outras podem ser incluídas.

Breadkpoints->Special trace e uma variação da opção Execute till BP, ela insere um Breakpoint imediatamente após a instrução selecionada e em seguida funciona como a Execute till BP.

A tecla [S] executa o comando STEP, e a tecla [T] executa o comando TRACE, com uma particularidade, neste caso, a execução do CALL é rápida, mas o Compass não tem como interceptar comandos que alterem o registro de slots, VDP ou a VRAM, e em alguns casos, o MSX vai travar.

A tecla [I] seta o SP para o valor que o mesmo tinha quando da carga do Compass.

A disposição do Debugger é ótima, pois em pouco espaço temos o disassembly, os registros, as flags, o stack, a seleção de slots e páginas, além do mini monitor, tudo isso facilita bastante a depuração.

Gerenciamento da Memória

Ao ser iniciado, o compass automaticamente configura a memória, mas permite mudanças na seleção dos blocos, e estas mudanças podem ser salvas usando a opção Installations->Main install->Save installations. Para acessar o mapeamento da memória, use a opção System->Memory.

Cada bloco recebe uma identificação de localização, como por exemplo:

  • 3-2 7: Este bloco está no terceiro slot primário, no segundo sub-slot, e no sétimo segmento da mapper
  • 1 20: Este se encontra no primeiro slot primário, e no vigésimo segmento da mapper
  • —: Este segmento não está selecionado

Para efetuar as mudanças, basta escolher com os cursores um bloco, pressionar [SPACE] e com as setas alterar o mapeamento, por exemplo, imagine que existem vários blocos alocados para o Source 2 (buffer de edição), por exemplo 3-2 19, 3-2 11, 3-2 10, 3-2 9 e 3-2 8, não existe espaço para o terceiro buffer (source 3),mas necessitamos de um terceiro buffer pequeno para uma edição rápida, podemos ir no Source 2, marcar, o último bloco com [SPACE] e mudar de 3-2 8 para — e dar [RETURN], em seguida, vamos ao source 3, no primeiro bloco que esta como —, pressionamos [SPACE] e com as setas escolhemos 3-2 8, dando [RETURN] no final, após as mudanças, basta salvar as configurações.

Infelizmente, não consegui fazer o esquema de memória funcionar corretamente, embora funcione bem para o Source 1 e 2, não funcionou para o 3 e 4, pode ser algo que eu não compreendi, ou se é um bug, assim que tiver mais informações, posto aqui mesmo.

Bom, outras áreas podem ser alteradas, inclusive a seleção dos slots, com algumas restrições:

  • O primeiro banco de labels e o segundo bloco do próprio compass, devem sempre estar na mapper primária.
  • Ao lado dos blocos de memória do Compass, existe a área de trabalho, que é usada como destino da montagem, é mostrada no monitor e no debugger, sendo permitida a alteração das páginas 0,1 e 2, mas nunca da 3, por conter as variáveis de sistema (isso já é esperado por todos).

Caso você tenha muita memória (acima de 6mb), pode ser que nem toda a memória possa ser mapeada por uma limitação do compass

Outra característica legal do Compass, relacionado a memória e a opção System->Slot view que mostra visualmente a disposição dos slots do MSX, identificando áreas críticas como BIOS, BASIC, FM, RAM, SUB-ROM, DISK-ROM, etc..

Macros e Compilação Condicional

Uma das mais poderosas caracteristicas dos bons assembladores, é o suporte a macros, e o Compass tem um suporte muito bom as mesmas, não tão completo quanto o M80, mas ainda assim, ótimo, já que suporta parametros e recursividade.As diretivas relacionadas as macros são:

MACRO [@param1, @param2, …], que é usada para iniciar a definição de uma macro, onde o @ é usado para diferenciar os parametros da macro dos labels.

ENDM, que encerra a definição da macro.

label: DEFL value, funciona exatamente igual ao EQU, mas só pode ser usado dentro da definição de uma macro.

Um comando especial pode ser usando dentro de uma macro: @sym, onde o montador ver este simbolo, ele troca por um valor que é incrementado a cada expansão da macro, ou seja, na primeira expansão ele vale 0000, na segunda 0001, e assim por diante, isso é util caso a macro defina alguns labels, permitindo assim usar a mesma em varios pontos, sem conflitar seus labels.

Exemplo 1

bc_de: macro @par1, @par2
         ld bc,@par1
         ld de,@par2
endm
...
    bc_de 123,#F04E

É montado como

ld bc,123
ld de,#F04E

ou

bc_de (#FBB1),#F04E

É montado como

ld bc,(#FBB1)
ld de,#F04E

Exemplo 2

print: macro @p1
         push hl
         ld hl,m@sym
         call mout
         pop hl
         jr l@sym
m@sym:
         db @p1,0
l@sym:
         endm

Isso gera uma rotina de impressão a cada expansão da macro, note que foi usado o @sym, então os labels definidos (m@sym e l@sym ) nunca irão conflitar, pois serão expandidos para m0000/l0000 na primeira vez, m0001/l0001 na segunda, e assim por diante, note também que o parametro foi usado em db @p1 mostrando o poder de definição das macros.

Exemplo 3

BDOS:    macro @fun, @fcb
         if "@fcb">""
             ld de,@fcb
         endif
         ld c,@fun
         call #0005
         endm

Neste exemplo, o registrador DE somente será carregado com o parametro @fcb, se o mesmo for passado para a macro.

Compilação Condicional

Os seguintes comandos estão disponíveis para a compilação condicional:

  • IF/COND parametro: Monta os comandos apenas se a condição for verdadeira (diferente de zero).
  • ELSE: Monta os comandos cado a condição de IF não seja satisfeita
  • ENDIF/ENDC: Encerra o bloco IF/ELSE

As condições podem ser expressões matemáticas ou comparação de strings, como o esperado, e podem ser aninhados até 16 IFs em sequencia.

Exemplo 4

if "Teste">"teste"
    if 1=2
        defs 50
    endif
    defs 100
endf

Programas Residentes e Programas Relocáveis

Programas Residentes

Os programas TSR somente podem ser criados quando você está executando o MemMan 2.4, já que o mesmo dá todo o suporte para a alocação de memória e a manutenção dos HOOKs de ativação, aqui apenas estou listando as opções necessárias para usar o Compass com TSR, em breve, devo colocar algum exemplo ou tutorial para criar TSRs neste blog.

A única diretiva relacionada com os TSRs é TSRHOOKS que deve ser usada antes de ser definido um hook. O programa deve ser compilado com a opção Assemble->Assemble to TSR, e o mesmo deve ser executado, pelo DOS, usando o comando TL. Caso o TSR não funcione corretamente, você pode voltar ao Compass, desde que use a função saída para o Shell.

Um programa TSR tem a aparência a seguir:

        code
        ...
        code
        TSRHOOKS
hooks:
        defw ..., ..., ...
        end

Programas Relocaveis

Já o suporte a programas relocáveis possui muito mais diretivas no Compass.

CSEG / DSEG / ASEG: A montagem usando arquivos relocáveis, permite usar 3 diferentes contadores, a saber, Code Segment, Data Segment e o Absolute Segment, estes segmentos serão juntados durante a linkagem, usando as diretivas, você informa em qual porção o próximo bloco deve ser inserido.

PUBLIC / EXTERN label, label, label,…: Usando Public, você informa que os labels declarados no módulo corrente, serão visíveis aos outros módulos, e se um módulo deseja usar um label de outro, basta declarar o mesmo como EXTERN.

.PHASE #NNNN /.DEPHASE:  Pode se usar a diretiva Phase para indicar que o PC irá assumir o endereço #NNNN, sendo que todos os labels compreendidos entre o .PHASE e o .DEPHASE serão jogados a partir deste endereço.

Exemplo básico de programa relocavel:

;
; PROG1.ASM
;
cseg
        extrn PRINT
PROG1   ld de,TEXTO
        call PRINT
        ret
dseg
TEXTO   defb "Ola Mundo!$"
;
; PROG2.ASM
;
BDOS    equ #05
cseg
        public PRINT
PRINT   push bc
        ld c,9
        call BDOS
        pop bc
        ret

Compilação, use a opcao Aseemble->Assemble to REL nos dois programas, vai gerar os arquivos PROG1.REL e PROG2.REL, usando o link do M80/L80, digite o seguinte na linha de comando:

L80 PROG/N,PROG1/E/P:100,PROG2

Vai gerar o arquivo PROG.COM.