Como criar um sistema operacional 32-bit em c & assembly


#1

Olá malta!

Trago um tutorial bem simples, que pode ajudar a criar um kernel em linguagem c e assembly, como é de hábito não ensinarei nada sobre linguagem de programação, certifique-se de que tenha no mínimo o domínio do assunto, e seja capaz de lidar com as linguagens de programação c e assembly.

Condicionamento:
É necessário ser usuário do Linux, para o devido funcionamento.

Ferramentas:
nasm
gcc
make
qemu
Editor de texto, do tipo bloco de notas

Introdução
Estou escrevendo este tutorial acreditando que, o referido leitor já tenha, experiências em compilar no ambiente Linux. Procurando ser o mais breve possível.

Para fazer funcionar nosso kernel, precisaremos de um carregador (bootloader), estou propondo em usar, o meu próprio bootloader que criei, podemos obter a imagem de disco virtual aqui, salve-a em um local próximo de preferência na pasta do projecto.

Sem mais rodeio vamos ao assunto.

;Arquivo start.asm

bits 32
section .text
global start
start:
mov ax,0x10  ; Aponta segmento de dados no GDT    
mov ds,ax
mov ss,ax
mov esp, _pilha
xor eax,eax
mov es,ax
mov fs,ax
mov gs,ax

	jmp MAIN

; Estas informações são exteriores ao script kernel.ld
		EXTERN code, bss, end
		dd code
		dd bss
		dd end
		dd start

MAIN:
	
    	extern main
		call main  ; Executa código em C
LP:
	HLT ; Coloca o CPU para dormir.
JMP LP

   section .bss
   global _pilha
   resb 8192 ; 8 KiB
  _pilha:

Para compilar, via terminal execute: $ nasm -f elf32 start.asm -o start.o

Certo! Agora vamos criar o arquivo c

// Arquivo main.c

unsigned short *video = (unsigned short*)0xB8000;  // Memória de vídeo

static void puts(char *string,int attr);

void main()
{

   puts("Eu amo Kernel!",0xE);

} 



// Função imprime caracter na tela

static void puts(char *string,int attr)
{

   while(*string !=0)
    {

    *video = *string | (attr << 8);
    string++;
    video++;
    }

}

Para compilar , via terminal executa: $ gcc -Wall -O3 -m32 -ffreestanding -nostdlib -nostdinc -c main.c

Muito bem! Ainda precisaremos de um terceiro arquivo, que nos permita juntar os códigos objectos

/* Arquivo kernel.ld    */

/* Não sei vocês, mas eu sempre, alinho meus códigos para 4 KiB, devido a paginação */



OUTPUT_FORMAT("binary")
OUTPUT_ARCH(i386)
ENTRY(start)

phys = 0x100000;

SECTIONS
{
    .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(4096);
}
    .data : AT(phys + (data - code))
{
    data = .;
    *(.data)
    . = ALIGN(4096);
}
  .bss : AT(phys + (bss - code))
{
    bss = .;
    *(.bss)
    . = ALIGN(4096);
}
     end = .;
}

Certo! Já podemos juntar nossos objectos e gerar o código binário que nos interessa
Via terminal executa: $ ld -T kernel.ld -o kernel.bin start.o main.o

Agora, já temos a imagem binária, agora só nos resta executar o kernel. Para isto criei um bootloader que nos permite carregar nosso kernel na memória, e executá-lo. Se ainda não o fizeste, faça o download aqui, e salve-a na pasta do projecto.

salva

Agora, no terminal, linha por linha executa:

$ sudo mount kholeOS.img /mnt/
$ sudo rm /mnt/kernel/kernel.bin
$ sudo cp kernel.bin /mnt/kernel/
$ sudo umount /mnt/

E por fim podemos testá-lo no VM (qemu), para testar, via terminal executa: $ qemu-system-i386 -m 512 -drive file=kholeOS.img,index=0,format=raw,media=disk

Você deve esperar por pelo menos 9 segundos para ver o resultado. “A paciência pois é amiga da perfeição”.

Se ficou como na imagem abaixo “Parabéns”, caso contrário, revê o tutorial.

Baixe o resultado final Aqui! Mas é claro que automatizei um pouquinho com o make, no arquivo Makefile

O repositório do tutorial. Aqui!
Meu repositório Aqui!

Obrigado! Toda crítica é bem-vinda. Até breve!


#2

Muito bom @nelsoncole

Parabens pelo tutorial. Continue assim…

E antes que eu me esqueça:

section .data
msg db 'Seja Bem-Vindo!!!', 0AH
len equ $-msf

section .text
global _start
_start: mov edx, len
    mov ecx, msg
    mov ebx, 1
    mov eax, 4
    int 80h

    mov ebx, 0
    mov eax, 1
    int 80h

Abraços


#3

Hahahaha! Obrigado.

Gostei do bloco de código.


#4

Legal Nelson!
Porém o titulo pareceu um pouco hiperbólico na primeira instância em contacto com o artigo.
Mas o artigo ficou legal, quando puder, vou também contribuir de tal grau semelhante.
Continue nessa, assim estimulam os outros devs a contribuírem também! :slight_smile:


#5

Agora ficou em c e assembly.