Criando um sistema operacional com ASM e C++

O assunto que não é muito difundido, ganha um novo episódio. Com uma didática direcionada ao publico leigo e mediano, veja como é possível criar seu próprio núcleo básico de sistema operacional do zero, com Assembly e C++. Um desafio realmente tangível.

[ Hits: 59.445 ]

Por: Gabriel Marinho em 11/09/2013


Introdução / Preparação



Coragem e uma breve introdução sobre a reinvenção da roda

A construção de sistemas operacionais não é algo comum de se ouvir hoje em dia, mas, desperta o interesse de muitos para realmente saber como as coisas funcionam debaixo dos panos.

Sim, por trás da tela gráfica e até mesmo por trás da tela preta do terminal.

Abordarei hoje, a criação de um kernel do zero.

Kernel é o núcleo do sistema operacional. Ele controla, dependendo do paradigma escolhido, praticamente tudo em seu computador. Pode gerenciar Hardware (aquele Pendrive que você conectou na máquina, foi ele que reconheceu e o deixou acessível a você), distribui e organiza recursos de todo o sistema.

O kernel que criaremos em questão, será algo muito simples. Ele será capaz de ligar uma máquina de arquitetura x86 e escrever "hello world" na tela. Servirá apenas para entusiasmar sobre o assunto e mostrar que, com um pouco de esforço, é realmente possível fazer um simples sistema operacional.

O artigo é direcionado a todos os públicos. Desde o leigo e médio entendedor do assunto, até às pessoas mais avançadas. Se você não parou de ler até aqui, é um bom sinal, você está disposto a encarar o desafio!

Mas antes, vamos recapitular algumas regras:
  • Para que nada dê errado, leia o artigo em sua respectiva ordem, deixe o autor leva-lo passo por passo, um de cada vez. Mesmo com um assunto extenso, prometo não ser chato.
  • Caso tenha algum termo que você, por acaso, não conheça, pesquise sem medo. O intuito de tudo é realmente isso. Os dois lados aprenderem.
  • Se algo não der certo, coisa que acontece muito quando o assunto é este, não desanime. Tente quantas vezes forem necessárias para seu sucesso.
  • As linguagens escolhidas para a criação de nosso sistema operacional são C++ e Netwide Assembly (ASM). Caso não conheça, sugiro uma pesquisa elevada sobre isso.
  • Rodar Kernels caseiros em máquinas reais, pode gerar efeitos colaterais graves. Então, pelo amor de Deus, não rode isso em uma máquina real. Todos os testes serão feitos dentro de máquinas virtuais que não oferecem risco nenhum a saúde de seu micro. Se você for doido o bastante para fazer isso, tire uma foto e me mande. Caso queira, faça por sua conta e risco.

Será divertido... Acredite!

Preparando o ambiente

Para conseguirmos fazer nosso sistema operacional, será necessário algumas ferramentas de programação instaladas em seu computador.

Para o artigo, foi utilizada a distribuição Slackware 14 32 bits.

* Algumas pessoas têm problemas ao compilar o kernel em sistemas operacionais x86_64, então, é recomendado que você use um sistema operacional apenas 32 bits para a tarefa.

Foi realizado um teste com a distribuição Ubuntu 13.04 x86_64 em uma máquina da universidade em que estudo. Funcionou perfeitamente, apenas necessitando instalar os pacotes necessários.

As ferramentas em questão, são (detalhe: tudo é feito com ferramentas livres):
  • NASM (Netwide Assembler)
  • G++ (GNU C++ Compiler)
  • ld (GNU linker)
  • Make (GNU Make)
  • QEMU (Virtual Machine)
  • Git (SCM)

Caso esteja na distribuição Ubuntu, ou qualquer outra derivada de Debian, use o comando:

# apt-get install nasm g++ make qemu make git

* Nota: o ld não consta na lista, mas é instalado como dependência do G++.

Caso contrário, existem vários artigos aqui no VOL sobre a instalação destas ferramentas, pois sairia mais ainda do escopo do artigo explicar meios de instalar em outros gerenciadores de pacotes mais complexos, ou mostrar meios de compilação das ferramentas citadas.

ErdOS: a proposta "tangível" antes de começarmos

O projeto ErdOS (sim, é em homenagem a Paul Erdős) é a proposta de um sistema operacional apenas para o aprendizado. Nele, contém tudo o que faremos neste artigo.

Caso queira ver como seu trabalho ficará antes de começarmos, ou ter mais informações sobre o projeto, basta clonar o repositório em seu micro e simplesmente rodar o comando make, para que tudo seja devidamente construído.

Detalhando mais, com nosso ambiente anteriormente pronto, só precisamos...

Já em seu respectivo diretório, criado exclusivamente para testes, faça o clone do repo...

git clone git@github.com:gabrielbiga/ErdOS.git

Depois de concluído, basta entrar como root e construir o sistema ErdOS.

Nota: o comando make deve ser rodado como root, pois utiliza "mount" para editar a imagem do GRUB, portanto, sendo estritamente necessárias permissões elevadas:

su
# make


Ou:

sudo make

Ao término, se tudo ocorrer bem, será gerado 2 arquivos na pasta bin:
  • erdos.img
  • kernel.bin

"erdos.img" é, nada mais do que uma imagem de disquete com seu kernel recentemente gerado, atrelado ao GRUB (nosso bootloader). Você pode gravar num disquete físico ou testar com o QEMU:

# qemu-system-i386 -fda erdos.img

E "kernel.bin", é seu kernel compilado. Para testar o kernel sem precisar usar um bootloader, é completamente possível utilizando:

# qemu-system-i386 -kernel kernel.bin

    Próxima página

Páginas do artigo
   1. Introdução / Preparação
   2. Estrutura de arquivos
   3. Compilação e linkagem
Outros artigos deste autor

Configurando o X e a placa de vídeo NVidia no Debian Sarge

Tocando arquivos MP3 no SuSE Linux

Leitura recomendada

Tutorial OpenGL

Criando aplicativos para o Mac OS X no GNU/Linux

Utilizando a biblioteca NCURSES - Parte II

Programando com uma granada de mão: uma visão da linguagem C

Brincando com o editor HT

  
Comentários
[1] Comentário enviado por lcavalheiro em 11/09/2013 - 04:09h

Hm... Realmente interessante

[2] Comentário enviado por zendrael em 11/09/2013 - 14:15h

Gabriel, legal o artigo!

Tem como compilar pra ARM?

[3] Comentário enviado por gabrielbiga em 11/09/2013 - 14:42h

Infelizmente não zendrael. Para rodar em ARM teriam que ser feitas algumas mudanças no lançador, meios de compilação e a troca do bootloader para um GRUB que rode em ARM. Mas está ai uma outra coisa legal a se fazer com o projeto... Um port para ARM. Voluntários? :)

[4] Comentário enviado por zendrael em 11/09/2013 - 14:59h


[3] Comentário enviado por gabrielbiga em 11/09/2013 - 14:42h:

Infelizmente não zendrael. Para rodar em ARM teriam que ser feitas algumas mudanças no lançador, meios de compilação e a troca do bootloader para um GRUB que rode em ARM. Mas está ai uma outra coisa legal a se fazer com o projeto... Um port para ARM. Voluntários? :)


Opa, eu topo! Só não sei por onde começar... Hahahah!

Talvez usando o uBoot para ARM já resolva/ajude em alguma coisa!

[5] Comentário enviado por Anonymous267 em 12/09/2013 - 10:29h

Interessante e fácil de ser feito o seu tutorial vou tentar fazer aqui obrigado.

[6] Comentário enviado por dannyalisson em 12/09/2013 - 16:58h

Parabéns, excelente artigo.

[7] Comentário enviado por Buckminster em 12/09/2013 - 19:19h

Muito bom. Parabéns.

[8] Comentário enviado por lucas-lks em 16/09/2013 - 07:42h

Muito bom! Parabéns pelo artigo, muito interessante =)

[9] Comentário enviado por lucasdona em 17/09/2013 - 15:55h

Zendrael, acho que com o código para compilar, pode tentar compilar utilizando o yocto ou Ltib.
Trabalho um pouco com arm e, já consegui compilar um drive de uma tela de toque para um arm com um kernel especifico, utilizando o código fonte do kernel que incluia o driver da tala tmb (usbtouchscreen.c). Acredito que seja possível também compilar todo o kernel.

[10] Comentário enviado por c4s3 em 25/09/2013 - 12:55h

zendrael, cara muito bom o seu post. vc conheçe outros lugares onde eu possa encontrar mais info de como começar a desenvolver a minha própria distro?

[11] Comentário enviado por marceloiaverafa em 22/11/2013 - 13:36h

quando executei este comando no terminal:

$ g++ -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -fpermissive -m32 -c libc/io.cpp

ele retornou:

libc/io.cpp: Na função ‘void std::escrever(char*, int)’:
libc/io.cpp:10:20: aviso: conversão de ‘int’ para ‘char*’ inválida [-fpermissive]
libc/io.cpp:16:16: aviso: conversão de ‘char*’ para ‘char’ inválida [-fpermissive]

[12] Comentário enviado por heitor_neto em 25/02/2014 - 14:19h

Como faço para criar o meu proprio disco de boot.

[13] Comentário enviado por SirCode em 05/12/2015 - 13:30h

Pode me explicar como funciona esses códigos ?
Essa parte principalmente não entendi nada:
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_AOUT_KLUDGE equ 1<<16
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
Essa tambem:
EXTERN code, bss, end
Essa:
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM

dd multiboot
dd code
dd bss
dd end
dd start
Não entendi a ultima linha do start.asm
E não entendi o link.ld
E como que a variavel mem do io.cpp vai escrever na tela ?

[14] Comentário enviado por SirCode em 05/12/2015 - 13:44h

Pode fazer uma parte de como detectar o keypress ?

[15] Comentário enviado por Uchiha Beyond em 07/07/2016 - 05:02h

Pelo que reparei ele funciona apenas com o modulo para video, como ele funciona sem mudulo para o processador, Memoria RAM e Armazenamento de Memoria?

[16] Comentário enviado por nelsoncole em 15/06/2017 - 18:17h

Bom tutorial !

Ai porquê que ele parou simplesmente no "Hello World"?

[17] Comentário enviado por nelsoncole em 23/06/2017 - 22:15h

Vejo que o artigo foi criado 11/09/2013. Gostaria de poder contribuir com o projecto, adicionando nele os descritores de seguimento e de interrupção, fazer funcionar pelo menos 5 das IRQs e criar um biblioteca mais próxima a Libc.
Infelizmente não estou recebendo atenção do altor inicial.

[18] Comentário enviado por Ashura em 04/07/2017 - 14:09h

Amei ;)
I Love Programming!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts