Ir para conteúdo
Faça parte da equipe! (2024) ×

Criando seu OS


AceStryker
 Compartilhar

Posts Recomendados

Introdução

 

Hoje vou ensinar a vocês garotos como criar um sistema operacional de verdade, não aqueles que o Rique fazia(sem ofensa).Nosso sistema operacional vai fazer basicamente nos trará uma mensagem ao iniciar o computador e quando apertarmos alguma tecla ele vai reiniciar.Basicamente aparenta ser fácil, mas há muita teoria em cima disso, espero que gostem...

 

PS:Se você não tem um conhecimento intermediário em assembly, nem comece a ler.

 

Emu086:

EMU8086

Este programa compila/debuga/emula o seu OS, vamos usa-lo bastante.

 

Fergo RawImage Maker:

Fergonez.net - Download File

Este programa cria imagens, nós precisaremos deve para converter os arquivos do Emu para uma image...

 

RawWriteWin

chrysocome.net - RawWrite for Windows

Este programa grava a imagem no disco, precisaremos disto mais tarde também.

 

O BOOT

 

Quando ligamos o computador, ele automaticamente checa todo o hardware antes de abrir o sistema operacional, depois disso, o computador checa os primeiros 512 bytes do disco para ver se tem um sistema operacional nele, caso não encontre, ele busca no MBR(Master Boot Record) do seu HD.

 

Se ele encontrar algum sistema operacional nestes 512 bytes de memória, ele os carrega no endereço 0000:7C00h ("h" de hexadecimal), veremos agora como funciona estes endereços:

Quando se usa o formato xxxx:yyyy é que estamos trabalhando com endereços relativos.A primeira sequencia é chamada de Segment e a segunda parte se chama Offset.Para calcular o endereço fisico precisamos saber desta formula aqui:

 

Segment * 16h + Offset = Endereço físico

 

Tomando como exemplo o local onde a BIOS carrega o sistema operacional, podemos

calcular o endereço físico real através do cálculo:

 

0000h * 16h + 7C00h = 7C00h

 

Nosso sistema é carregado no endereço físico da memória 7C00h. É bom lembrar que

diferentes segments e offsets podem gerar o mesmo endereço físico. Por exemplo:

 

0000:7C00h = 07C0:0000h

 

Qual a importância de saber sobre esses endereços? Bom, é por eles que você vai

controlar seu programa. Você pode usar endereços físicos diretamente, mas usando

no formato de segment/offset você consegue organizar melhor as posições de

memória.

 

O endereço físico também é importante para saber onde eu posso e onde eu não

posso gravar os dados na memória. A BIOS reserva um trecho de memória baixa (

640KB ) para que você use-o livremente. Esse trecho vai do endereço físico 00500h até A0000h. Ou seja, você não deve gravar nada antes do endereço 00500h e nem após A0000 ( são locais reservados para memória de vídeo, bios, vetores de interrupts ( veja adiante ), etc... ).

Voltando ao boot. Eu mencionei que ele carrega os 512 bytes do primeiro setor na

memória. Certo, e se meu SO tiver mais de 512 bytes? Aí nos vamos precisar de um

Loader, que é basicamente uma seqüência de instruções ( com no máximo 512 bytes

para caber no primeiro setor ), que é responsável por carregar o Kernel do disco para a

memória. Vamos usar um para o nosso SO ( apesar de não precisar nesse caso ).

 

Interrups

 

Interrupt, no caso do Assembly, é uma instrução que paralisa o código atual para que

alguma ação seja realizada ( chamamos isso de IRQ – Interruption Request ). Se for

para comparar com algo nas linguagens de alto nível, podemos comparar ele com uma

função, que é chamada, executa suas instruções, e depois retorna para o código onde

ela foi chamada.

Todo computador na arquitetura x86 possui diversos interrupts, controlados pela BIOS.

Os interrupts são compostos por uma função e uma subfunção. Por exemplo, para

trabalhar com o vídeo, é usado o interrupt 10h. E a operação a ser realizada no vídeo (

subfunção ), depende do valor de algum registrador ( normalmente AH ). Veja o

exemplo abaixo que imprime um caractere na tela:

 

É necessário se cadastrar para acessar o conteúdo.

 

Como eu sei o que cada interrupt faz, quais os argumentos e quais registradores estão

envolvidos? Eu uso este site: Interrupt Services DOS, BIOS, EMS und Mouse

Vamos usar Interrupts para imprimir caracteres na tela, para buscar por teclas

pressionadas, para alterar o modo de vídeo, etc. Dá pra notar que entender o seu

funcionamento é fundamental para prosseguir com este tutorial.

Vamos por a mão na massa agora.

 

Criando o Loader

 

O Loader basicamente consiste num conjunto de instruções que devem caber no

primeiro setor do disco ( 512b ) e que lê os outros setores do mesmo ( onde está o

Kernel e o resto do código ) para a memória.

O nosso código precisa configurar algumas coisas básicas para que tudo funcione

corretamente. Precisamos ter uma pilha de dados ( Stack ). Se você programa em

Assembly, deve saber o que é uma pilha, como ela funciona, e para que é usada.

Os registradores envolvidos com a pilha são os seguintes:

 

SS -> Stack Segment -> Aponta para o segmento onde está a pilha

SP -> Stack Pointer -> Aponta para determinada região da pilha ( normalmente o topo )

 

Além da pilha, é necessário indicar onde está o nosso segmento de dados

DS -> Data Segment -> Aponta para a base de dados ( usado sempre que for acessar

algum endereço de memória ).

Vamos organizar nossa memória da seguinte maneira:

Memória Descrição

 

07C0:0000 até 07C0:01FF Local onde foi carregado o bootloader

07C0:0200 até 07C0:03FF Pilha

0800:0000 em diante Nosso Kernel

Essa estrutura da memória é a mesma utilizada no site do Emu8086, pois é bem

didática e segue uma sequência lógica. Claro que vai ficar um bom trecho sobrando (

de 0500 até 7C00 ), mas por enquanto é suficiente.

Então eis a seqüência que vamos usar no nosso Loader

 

• Determina a pilha e seus registradores

• Indica o segmento de dados

• Altera o formato de vídeo para 80x25 ( 80 colunas, 25 linhas )

• Lê o setor do disquete onde está o Kernel

• Escreve os dados lidos no endereço 0800:0000

• Pula para este endereço e passa o controle para o Kernel

 

Abra o Emu8086, selecione ‘New’ e marque a opção ‘Empty Workspace’. Em seguida,

cole o código da página seguinte ( vou fazer os comentários sobre o que cada instrução faz no próprio código)

É necessário se cadastrar para acessar o conteúdo.

 

Observações:

O número de setores a serem lidos varia com o tamanho do Kernel. Cada setor tem

512 bytes. Então se o Kernel tiver 512 bytes ou menos, basta ler 1 setor. Se tiver 700

bytes, precisa ler 2 setores e assim por diante.

Caso tenha surgido alguma dúvida quanto aos valores, vá até o site com a lista de

interrupts que eu indiquei e analise a Int em questão.

Salve este código e compile através do botão ‘compile’ na barra de ferramentas. Ele vai

perguntar onde você deseja salvar o arquivo ( que vai ter a extensão .bin ). Dê um

nome qualquer ( algo como loader.bin ) e salve no diretório que desejar.

 

Criando o Kernel

 

Nosso Kernel vai ser o mais simples possível. Vai apenas escrever um texto na tela e

aguardar que o usuário pressione alguma tecla para reiniciar o computador. Parece

pouco, mas é suficiente pra você entender como um sistema básico funciona. Se

precisar que o Kernel faça algo mais ( claro que vai querer ), você já vai ter

conhecimento suficiente para poder usar outros interrupts e trabalhar melhor com a

memória, etc.

 

É necessário se cadastrar para acessar o conteúdo.

 

Mensagem db ‘Meu primeiro SO’,0 ;nossa string que vai ser exibida

Novamente, se tiver alguma dúvida quando a esse código ( que não seja relativo a

sintaxe e os comandos do Assembly ), volte ao site com a lista de interrupts.

Depois de pronto, salve o arquivo e compile, da mesma forma como fez no Loader.

Claro, escolha outro nome ( kernel.bin talvez ). Procure manter os arquivos em uma

mesma pasta, pra manter organizado.

Nosso mini sistema operacional está pronto. Só falta grava-lo no disquete e testar. 11

 

Gravando e Testando

 

Com os binários do Loader e do Kernel em mãos, vamos criar uma imagem para ser

gravada no disco, vamos usar agora o Fergo RawImage Maker.

 

Execute o programa. A interface é bem simples e intuitiva.

Preste bastante atenção nos setores que você for gravar.

Se tudo ocorreu bem, deve ter aparecido uma mensagem indicando que o arquivo foi

criado com sucesso.

Agora temos que gravar a nossa imagem no disco. Insira um disco vazio no

drive e abra o programa RawWriteWin. Configure o caminho para a imagem que

você acabou de criar ( tutorial.img no meu caso ) e clique em ‘Write’.

Se o disco estiver em bom estado e você seguiu os passos corretamente, deverá

receber novamente uma mensagem indicando que a imagem foi gravada com sucesso

no disco ( certifique de que ele não está protegido contra gravação ).

Agora basta testar. Coloque o disco no drive, reinicie o micro, configure para que a

BIOS dê o boot pelo disco e se deu tudo certo.

Se a mensagem apareceu, parabéns, você fez tudo corretamente. Caso ela não

tenha aparecido, releia o tutorial que com certeza você encontrará o local onde está o

erro.

 

Finalização

 

Espero que todos tenham gostado, qualquer duvida só me falar, tomara que ajude a todos...

 

Créditos:

 

AceStryker e Fernando Birck(Fergo)

Link para o comentário
Compartilhar em outros sites

Este tópico está impedido de receber novos posts.
 Compartilhar

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...

Informação Importante

Nós fazemos uso de cookies no seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies , caso contrário, vamos supor que você está bem para continuar.