![]() |
MC404 |
![]() |
Este documento cobre diversos assuntos relacionados à programação em linguagem de montagem:
Ao dar partida um PC executa um programa denominado BIOS contido na memória de programa não volátil (flash) do PC. Este programa oferece um conjunto de funções de E/S para o teclado, vídeo, disquete, disco rígido, etc, necessárias ao processo de partida (bootstrap) antes da carga do Sistema Operacional (feita a partir de um dos discos, podendo inclusive ser o DOS ou outro qualquer a partir de um disquete). Essas funções estão disponíveis a programas em assembler e são de nível mais baixo (isto é, mais perto do hardware), do que as funções do DOS: por exemplo, existem funções para saber se uma tecla foi levantada ou abaixada, para posicionar o cursor na tela, para definir as cores de foreground e background, tamanho do cursor, etc. Elas são usadas pelo programa inicial de boot que reside no 1º setor do disco de boot (e que por sua vez carrega o Sistema Operacional a partir de um ou mais arquivos no disco). Um resumo das funções do BIOS pode ser visto neste link. Vamos mencionar apenas as seguintes funções:
Um programa exemplo bem documentado que ilustra a criação de uma janela
e o seu preenchimento com duas mensagens usando funções do BIOS encontra-se neste
link. Este programa exibe um recurso interessante
só disponível em assembler e no venerável FORTRAN que é o de uma rotina
com múltiplos pontos de entrada.
A utilização das funções descritas de vídeo e teclado é também exemplificada
neste programa biosfun.asm que lê
15 mensagens do teclado, ecoando no vídeo cada mensagem com uma cor diferente.
O debug do DOS permite ler e escrever setores de um disquete ou o conteúdo
de um arquivo de forma bastante simples:
após invocar o debug (prompt -):
-L end-mem drive_no sector_no nsectors -L 0 0 0 1 -- lê a partir do endereço 0, 1º floppy, setor 0, 1 setor
-w 0 0 0 1
-n boot.bin -- abre o arquivo boot.bin para leitura -L 0 -- lê o arquivo boot.bin a partir da posição de memória 0
Quando um PC dá partida o BIOS carrega o 1º setor (512 bytes) do 1º disco habilitado para carregar o Sistema Operacional (e que pode ser o disquete, e que suporemos que é o caso no que se segue). Este setor (localizado no cilindro 0, face 0, setor 1) é lido a partir da posição de memória 7C00h e contém o programa inicial de boot do sistema. O BIOS valida o programa de boot verificando se os dois últimos bytes do setor carregado possuem os valores 55h e AAh. Nesse caso ele salta para a posição de carga, 7C00h, caso contrário emite uma mensagem de erro, tipicamente, "Invalid system disk" e aborta o processo. O programa do setor de boot contém uma área de dados com 60 bytes localizada a partir do 3º byte do setor, com informações sobre o sistema de arquivos do disquete (usualmente FAT12). Os dois 1ºs bytes contêm uma instrução de salto para além dessa área de dados onde começa propriamente o código de boot que consiste em ler do disquete os arquivos IO.SYS e MSDOS.SYS que são o núcleo do sistema operacional DOS.
O conteúdo do setor de boot para o nosso teste é irrelevante, apenas temos que garantir a existência dos bytes 55h e AAh nas duas últimas posições. Por exemplo, a área de dados não é necessária, mas se ela não existir o disquete não mais será reconhecido como um disquete DOS pelos sistemas operacionais da MS. Vamos então colocar um código arbitrário no setor de boot, que é justamente o programa biosfun.asm citado anteriormente e que exercita o vídeo e teclado usando funções do BIOS. A fim de evitar que a máquina fique travada após a emissão da última mensagem, (o usuário deverá então digitar <enter>) o programa desvia para a posição de memória FFFF0h do BIOS, que é onde processadores da família Intel X86 buscam a 1ª instrução após receber o sinal de reset (emitido quando ligamos a máquina). Se então retirarmos o disquete do drive o PC dará partida normalmente a partir do disco rígido.
Em resumo: qualquer programa em linguagem de máquina (binário) colocado no 1º setor de um disquete cujos últimos dois bytes contêm os valores 55h e AAh será executado pelo BIOS na partida de um PC habilitado a dar "boot" pelo disquete. Neste instante o PC estará sob seu contrôle! Para gerar esse programa é suficiente:
nasmw boot.asm -o boot.bin
debug -n boot.bin -L 0 -w 0 0 0 1 (você pode verificar nesse ponto se a gravação foi correta com os comandos -f 0 200 ff, -L 0 0 0 1 e -d0 -d -d -d , que exibirão os 4 x 128 bytes gravados) -q
A 1ª diretiva permite definir a variável BOOT. Nesse caso será gerada a
versão para gravação no setor de boot de um disquete, senão será gerado um arquivo
.COM usual.
No 1º caso gera-se o código com o salto inicial, a tabela de dados de
um disquete DOS com FAT12 e a inicialização dos registradores de segmento
DS, SS e ES com zero.
A partir do rótulo init o código é idêntico para as duas versões.
Em seguida a rotina initvideo inicializa uma janela do video com 25 linhas
e 80 colunas (numeradas a partir de 0) e exibe a mensagem inicial
que solicita a digitação pelo teclado de 15 mensagens. O laço principal do programa
(começando no rótulo l1) exibe sucessivamente a mensagem "Digite mais uma mensagem"
(chamando a rotina printmsg),
lê uma mensagem pelo teclado até ser digitado CR (rotina readline, que também
ecoa a mensagem no vídeo), e muda a cor de foreground do video.
O laço termina quando atinge a cor 0 (preta, não exibida pois é igual à de background)
e a mensagem final é exibida. No caso da versão de boot é lido novamente do teclado
um ou mais caracteres terminados por CR, a fim de dar tempo de exibir
no video a ultima mensagem, antes de reiniciar o PC através de um salto longo
para a posição(CS:IP) = ffff:0 (ou equivalentemente, f000:fff0 ) que dá partida ao PC
imediatamente após o reset. As rotinas seguintes dão suporte às rotinas
printmsg e readline usando funções do BIOS e são auto-explicativas
com auxílio do resumo citado de funções do bios.
No caso do setor de boot, as diretivas após a definição das mensagens
verificam se o código + dados não excedem 512 bytes, zeram os bytes seguintes
(diretiva times) e inicializam os dois últimos bytes com 55h e AAh.