Escolar Documentos
Profissional Documentos
Cultura Documentos
Montei esse material primeiro no Google Docs, se você quiser acessar o link é esse:
— HTTPS://DOCS.GOOGLE.COM/DOCUMENT/D/1EOBCSNWKII_1XXRNHTYRFWT6DNZC
IHDE1Z2CLZVOASM/EDIT?USP=SHARING
(HTTPS://DOCS.GOOGLE.COM/DOCUMENT/D/1EOBCSNWKII_1XXRNHTYRFWT6DNZCI
HDE1Z2CLZVOASM/EDIT?USP=SHARING)
criando-um-sistema-operacional-parte-1
(https://myfailcode.files.wordpress.com/2022/03/criando-um-sistema-operacional-parte-
1.pdf) Baixar (https://myfailcode.files.wordpress.com/2022/03/criando-um-sistema-
operacional-parte-1.pdf?force_download=true)
Antes de aprendermos a como criar um bootloader, primeiro temos que entender o que
acontece com o computador ao pressionarmos o botão de Ligar.
Quando pressionamos o botão de Ligar, a energia é enviada para a CPU e a mesma trata de
carregar um pequeno programa armazenado em um chip que fica localizado na placa mãe do
computador.
Ambiente e Ferramentas
Neste artigo, estaremos utilizando uma máquina baseada em Linux, essa escolha se deu
pelo fato de que a maioria das ferramentas que utilizaremos já estão nativas nesse tipo de
sistema operacional. As ferramentas utilizadas foram:
Essenciais:
Opcionais:
1. hexdump [4]
2. vim
3. gdb 8.3
Caso esteja em um sistema operacional baseado em linux que não tem essas ferramentas
basta executar o código abaixo para instalar:
O bootloader é um pequeno programa de inicialização do sistema que deve estar situado nos
primeiros 512 bytes do disco, sendo que no seu final deverá estar escrito o Magic Number
0xAA55, que é uma ‘assinatura’ pelo qual a BIOS reconhece que se trata de um dispositivo
válido ou não [5]. Basicamente o bootloader tem como objetivo principal fazer 3 coisas:
Ele é o responsável por direcionar o fluxo de execução para o kernel do sistema operacional,
agindo assim como um intermediador. A Figura 1 demonstra o processo simplificado.
Figura 1 – Processo de Boot Simplificado
A primeira região está abaixo de 1MB, conhecida como lower memory, na qual corresponde
todo o endereçamento disponível possível para o chamado modo real, tal modo trabalha no
máximo com 20 bits de endereçamento.
Já a segunda região é situada acima de 1MB, também conhecida como high memory que só
poderá ser acessada no modo protegido, com endereçamentos 32/64 bits.
A BIOS é responsável por carregar o bootloader que terá como destino o endereço de
memória 0x7c00 que corresponde a área chamada Boot Sector Area, percebe-se que esta área
vai de 0x7c00 até 0x7E00, correspondendo a 512 bytes, como pode ser visto na Figura 2.
Figura 2 – Organização da memória de um computador
Criando o arquivo
Agora que sabemos como funciona, podemos prosseguir. Estarei utilizando o editor de texto
vim do linux, mas pode ser empregado qualquer outro editor da sua escolha.
Nomearemos esse trecho acima como Comando 1. Desse jeito gerando um arquivo de saída
bootloader.bin, agora iremos executar o qemu com o seguinte comando:
$ qemu-system-x86_64 bootloader.bin
Nomearemos esse trecho acima como Comando 2. O resultado pode ser visto na Figura 3.
Um dos erros ocorrido foi o Boot failed: could not read the boot disk quando tentou fazer o
boot pelo Hard Disk no sistema, isso se deu pelo fato de que o arquivo está vazio e a BIOS não
encontrou o Magic Number.
times 512 db 0
Agora a mensagem de erro no Hard Disk mudou para Boot failed: not a bootable disk.
Isso significa que foi encontrado um dispositivo, mas não um que seja válido, pois lembrando,
necessita que no final tenha a assinatura 0xAA55 para ser reconhecido como um dispositivo
válido.
Entendo o binário
Para ter um outro ponto de vista do arquivo binário, iremos utilizar o seguinte comando:
Nomearemos esse trecho acima como Comando 3. A saída do programa você poderá ver na
Figura 5.
Figura 5 – Resultado do comando hexdump
Está preenchido com apenas 0 pois no arquivo só existe uma repetição para incluir o 0 em 512
bytes. Agora Iremos abrir de novo nosso arquivo bootloader.asm e acrescentar:
times 510 db 0
dw 0XAA55
Observe que de 512 foi para 510 pois o comando 0XAA55 corresponde a 2 bytes, sendo 1 byte
0xAA, e outro para 0x55, 510 bytes + 2 bytes totalizando os 512 bytes necessários para o Boot
Sector Area. Execute o Comando 1 e 2 respectivamente e a saída deverá ser como na Figura 6.
Figura 6 – Boot realizado
Se a mensagem que apareceu no qemu foi Booting from Hard Disk, isso indica que foi
realizado o boot corretamente, ou seja, agora temos um dispositivo válido. Se executarmos o
Comando 3 a saída deverá ser igual a da Figura 7.
Figura 7 – Resultado do Comando 3
Agora a BIOS já consegue encontrar o Magic Number, pois observa-se que o 0xAA55 está no
final do Figura 7, na área onde fica os hexadecimais, em forma de 55 aa, está ao contrário por
causa de alguns aspectos peculiares da arquitetura, que pode ser little endian ou big endian.
Escrevendo na Tela
caracteres na tela. Para que isso ocorra você primeiro deverá conhecer o conceito de
interrupções[6].
Como demonstra a Figura 2 e com mais detalhes a Figura 8, a memória tem uma região que se
chama IVT (Interrupt Vector Table) ou tabela de vetores de interrupção, que armazena os
endereços onde estão as rotinas de tratamento de cada interrupção chamadas de ISR
(Interrupt Service Routine) ou Rotina dos serviços de interrupção.
Figura 8 – Visualização do IVT na memória
Figura 9 – Fluxo de Execução de uma Interrupção
1. A interrupção 0x10 é a décima interrupção, então este número é multiplicado por 4, pois
cada elemento do vetor possui 4 bytes.
2. O endereço 0x40 é acessado na memória do IVT, e o conteúdo existente neste endereço
será um novo endereço onde se encontra o código dessa interrupção no ISR.
3. Pula-se para esse novo endereço.
4. A rotina de tratamento é executada.
5. O controle é retornado para o programa.
## TODO – Registradores
Todo esse fluxo pode ser visto na Figura 9. Iremos implementar uma chamada de sistema no
nosso arquivo, então abra o bootloader.asm e digite:
int 10h
times 510-($-$$) db 0
dw 0xAA55
Salve o arquivo e execute o Comando 1 e 2. Deverá aparecer na tela a letra “O” como na
Figura 10.
Pense nos código mov ah, 0X0E e mov al, 4Fh como parâmetros para função de interrupção int
10h, função está responsável pelos procedimentos relacionados ao vídeo, como a escrita de
caracteres na tela ou até mesmo alterar o modo de vídeo.
O valor 0x0E tem que ir para o registrador ah e significa que queremos entrar em modo texto,
já 4Fh é o valor da letra “O” em hexadecimal da tabela ASCII e tem que ir no registrador al.
Essas 3 primeiras linhas poderá ser feito uma analogia em C assim:
Onde o resultado final é um caractere escrito na tela, ou também similar a função putchar()
já existente do C.
Já a penúltima linha teve que ser modificada, pois como foi inserido mais bytes, se
continuasse a usar 510 bytes provavelmente iria ultrapassar a região do Boot Sector Area, para
resolver esse problemas adicionamos -($-$$) onde o $ significa o endereço de memória atual e
o $$ o endereço do início da seção atual, que no caso é o endereço inicial do arquivo.
Se quiser escrever mais caracteres é só repetir o mov al, 4Fh e int 10h no código, trocando o
conteúdo de al pela hexadecimal do caractere correspondente na tabela ASCII, e depois
sempre chamando a interrupção, como por exemplo:
;; O
int 10h
;; l
int 10h
;; a
int 10h
times 510-($-$$) db 0
dw 0xAA55
Referências
http://www.brackeen.com/vga/ (http://www.brackeen.com/vga/)
Sponsored Content