Para quem acha que ainda não desceu demais o nível existe um ótimo artigo no Code Project de S. Z. Keller (aka ShalomZ) sobre como construir seu próprio sistema operacional. É simples, direta e empolgante a maneira com que ele explica e trata os detalhes básicos, desde quando o computador é ligado até quando o boot loader carrega e entrega o controle de execução. Eu mesmo fiz o teste com a imagem que foi disponibilizada para download e funcionou direitinho. Agora esse meu artigo se dispõe a explicar como você pode fazer para depurar o processo de load do seu primeiro sistema operacional.
Primeiro precisamos de uma ferramenta fundamental para esse tipo de depuração: o SoftIce versão 16 bits. Desconheço algum outro depurador de sistema em 16 bits, mas se você souber de algum, pode usá-lo com esse tutorial com as devidas adaptações.
Passado o desafio inicial de encontrar essa versão do SoftIce e saber usá-la, o resto é fácil:
- Crie uma nova VMWare, Virtual PC, VMSbrubles configurada para bootar pelo disquete.
- Formate dois disquetes de MS-DOS, FreeDos, Sbrubles-DOS.
- Copie o setor de boot disponível no artigo do CP para o disquete usando o programa disponível em um dos disquetes.
- Copie o SoftIce no outro disquete.
- Efetue o boot com o disquete do SoftIce.
- Execute o SoftIce (é só rodar, ele permanece residente e é ativado com Ctrl + D).
- Coloque um breakpoint na int 0x13 (disco) na função 2 (leitura) (faz-se assim: bpint 13 ah=2).
- Troque o disquete do Softice pelo disquete com o setor de boot do artigo do CP.
- Efetue novamente o boot na máquina em modo "quente" (usando o próprio SoftIce, comando boot).
- A execução deve ser paralisada exatamente no ponto onde o código da BIOS lê o setor de boot do seu disquete.
- Digite p ret e em seguida F10 ou T e seja feliz.
Pelo softice 16 bits conseguimos parar a execução nas interrupções da BIOS e ainda especificar qual das funções será executada, definida no registrador AH; mais detalhes sobre layout de memória do 8086 no artigo do DQ 1.
Quando o código da BIOS é executado, ele precisa, entre outras coisas, fazer três:
- Encontrar o dispositivo padrão de boot.
- Ler o primeiro setor desse dispositivo para o endereço 0x7C00.
- Entregar a execução para o código em 0x7C00.
O item 2 é justamente o que utiliza essa interrupção para ler do disco. Eu prefiri colocar o breakpoint no item 2, mas nada impediria de você colocá-lo no item 3 e já iniciar a depuração no código do boot loader. Mas, como eu já passei por problemas encontrados no código da BIOS que impediam o sistema de entregar a execução para o setor de boot, já dei a dica de lambuja caso você também tenha a oportunidade de se divertir em um cliente depurando a BIOS de algum laptop desajustado.
A referência para saber quais as funções para cada interrupção na hora de depurar a BIOS pode ser encontrada em listas como a Ralf Brown's Interrupt List 2
A partir dessa leitura se usa o comando p ret do depurador, que é mais ou menos o step out do SoftIce 32. Ou seja, ele avança a execução até a função retornar. No caso do SoftIce 16 ele irá avançar até o próximo ret/iret. Por isso que também precisamos executar a próxima instrução (o próprio ret) para cair onde queremos. É nesse ponto que o "nosso" código começa a executar e onde conseguimos colocar breakpoints "de verdade", ou seja, escrevendo no parte do código que deve ser interrompida a chamada da interrupção de breakpoint (int 3). Lembre-se que não é isso o que é feito para parar no código da BIOS, uma vez que esta reside em memória de somente leitura (pelo menos durante a execução).
-
Gerenciamento de memória 386 - Daniel Quadros ↩︎