----------- ----- ---------------------------------------------------------- ---- ----------- #### #### ## #### ## ## #### # # # # # # # # # # # # # #### ### # # #### # # #### # # # # # # # # # # # #### #### ## #### # #### #### ----------- ----- ---------------------------------------------------------- ---- ----------- ----------- Tutorial sobre escrita de Sistemas Operacionais por s0ul ----------- ----------- ----- ---------------------------------------------------------- ---- ----------- mail: xs0ul@linuxmail.org irc: irc.brasnet.org #call #assemblybr icq: 175095418 ----------- ----- ---------------------------------------------------------- ---- ----------- Bom, como tenho pesquisado este assunto ( osdevel ), logo percebi que falta material sobre isto, se voce pesquisar bem tem sim mas todos em ingles, pensando nisso resolvi criar este tutorial que ira te ensinar como começar a criação de seu proprio Sistema Operacional, um conhecimento de assembly e a linguagem C sera preciso, vamos la. ----------- ----- ---------------------------------------------------------- ---- ----------- ----------- ----- ---------------------------------------------------------- ---- ----------- Primeiro vamos saber como nosto boot vai funcionar. Para podermos criar nosto boot sector teremos que conhecer algumas regras que devem ser seguidas, são elas: 1- Nosso boot sector deve conter exatamente 512 bytes, por que? Bom, porque a bios vai carregar na memoria o primeiro setor ( no caso do floppy disk ) 2- O boot sector deve conter o bootloader signature que seria 0x55AA. Ou seja, os dois ultimos bytes deve conter o bootloader signature, que seria os bytes 511 e 512 3- Nosso boot sector sera escrito em assembly, logo nao podera ter interrupções DOS ( int 21, int 20, etc.. ), como tambem nem pensar nas syscalls do linux, pois pense bem, voce estara criando um OS do zero, ou seja, ali nao vai ter nada, tudo zerado, quem manda é voce, voce esta no controle, usaremos interrupões da bios para faze-lo 4- O começo de nosso codigo deve ser em 16bits pois estaremos em real mode Antes de proceguir é bom que voce saiba que o codigo do nosso bootsector deve ser carregado no endereço 0x7C00. Para nao ter complicações vamos criando nosso bootsector pouco a pouco para que voce nao se perca no codigo ok. Bom, o esquema de nosso boot sector segue assim: ---------------------------------------------------------------------------------------------- [ORG 0x7C00] <<-- O codigo começa neste endereço da memoria [BITS 16] <<-- Aqui trabalharemos com 16bits ( real mode ) main: <<-- Inicio do codigo principal ... <<-- Bom aqui seguira colocaremos nosso codigo ... ... times 510 -($-$$) db 0 <<-- Preenchemos o resto com zeros, pois nosso boots deve conter 512 bytes. 511 e 512 deve conter a signature ----------------------------------------------------------------------------------------------- Voce aprendeu como montar o nosso codigo inicial, agora vamos criar um boot sector que mostra uma simples mensagem na tela " Welcome to my OS " e logo depois fica em loop, antes vamos conhecer as interrupções que iremos usar. Bom para mostrar nossa mensagem na tela, vamos usar a interrupção 0x10 que é da bios, a função para mostrar um caractere na tela é 0x0E, esta função segue assim: ah = 0x0E al = Caractere ASCII para mostrar na tela bl = Atributo do texto, onde definimos a cor bh = Numero da pagina ( modo texto ) Logo temos o seguinte: ah = 0x0E al = Caractere bl = 0x07 bh = 0x0 Agora vamos criar nosso primeiro boot sector ;-------------------------------------- boots.asm -------------------------------------- ; Boot sector para tutorial sobre osdevel por s0ul ; Compile: nasm boots.asm -o boots.bin -fbin ; obs.: pode ser compilado no windows ou no linux [ORG 0x7C00] [BITS 16] main: call _printstr ; Mostra mensagem na tela jmp $ ; Entra em loop infinito _printstr: mov si,mstart ; Si aponta para mensagem inicial mov ah,0x0E ; Função "Write Text" mov bl,0x07 ; Foreground Color mov bh,0x0 ; Numero da pagina .loop: ; Começo do LOOP <<-------------------------| lodsb ; Pega um caractere de si e incrementa si | or al,al ; verifica se teminou | jz .endloop ; se terminou pula | int 0x10 ; Senao printa na tela | jmp .loop ; Volta ao loop | .endloop: ; Fim do LOOP <<-------------------------| ret ; Retorna mstart db 'Welcome to my OS',13,10,0 times 510-($-$$) db 0 ;dw 0x55,0xAA ;----------------------------------------- Fim ------------------------------------------- Pronto, ai esta o nosso boot sector, mas e agora? como vamos coloca-lo para funcionar? Lembra de quando eu falei que nosso boot sector tem que estar no primeiro setor do nosso floppy disk? e outra coisa, os bytes 511 e 512 tem que conter o boot loader signature, que lembrando é 0x55AA, bom agora vamos criar um programa que faça isto para nos, aqui eu vou faze-lo em C, mas pode perfeitamente ser feito em assembly. Nosso programa vai se chamar " Boot Writer ", o que ele vai fazer? 1- Carregar nosso boot sector na memoria 2- Alterar os bytes 511 e 512, para a signature 0x55AA 3- Grava-lo no primeiro setor do floppy disk Vamos la. //------------------------------------ BootWriter.c --------------------------------------- // BootWriter feito para tutorial sobre osdevel por s0ul // gcc -o bootw bootwriter.c // ./bootw #include #include int main(int argc,char *argv[]) { char bufb[512]; int fdisk,bdisk; if (argc < 3) { printf("\n\n BootW by s0ul\n"); printf(" use: %s \n\n",argv[0]); exit(0); } printf("\n\n:: Abrindo Boot Sector"); bdisk = open(argv[1],O_RDONLY); printf("\n:: OK"); read(bdisk,bufb,510); close(bdisk); printf("\n:: Setando como boot file"); bufb[510] = 0x55; bufb[511] = 0xAA; printf("\n:: Boot signature 0x55AA gravado"); fdisk = open(argv[2],O_RDWR); lseek(fdisk,0,SEEK_SET); write(fdisk,bufb,512); printf("\n:: OK.. Boot Sector Gravado com sucesso\n\n"); close(fdisk); } //-------------------------------------- FIM ---------------------------------------------- Ai esta o nosso boot writer pronto, para usa-lo é simples, primeiro coloque um floppy disk em seu drive ( nao monte ), logo depois digite em seu console: [s0ul@root tests]$ nasm boots.asm -o boots.bin -fbin [s0ul@root tests]$ ./bootw BootWriter by s0ul use: ./bootw [s0ul@root tests]$ ./bootw boots.bin /dev/fd0 :: Abrindo Boot Sector :: Setando como boot file :: Boot signature 0x55AA gravado :: OK.. Boot sector gravado com sucesso [s0ul@root tests]$ Ok, agora o boot sector esta gravado em nosso floppy disk e pronto para ser usado, para usar, basta voce reiniciar o seu computador com o floppy disk no drive, bom, se nao for procurado boot no floppy, voce pode setar isto no setup, esta parte eu deixo com voce ;) Agora pense comigo, vai ficar muito chato voce ficar reiniciando o computador direto so para testar seu boot sector, bom se este é o problema nos podemos utilizar o bochs para testa-lo, o bochs pode ser baixado no site so sourceforge, tanto para windows como para linux. Abaixo segue o esquema para voce poder usar seu bootsector com o bochs: 1- Criar uma imagem do disco chamado disk.img 2- Colocar seu boot sector dentro desta imagem com o Boot Writer 3- Criar o arquivo de configuração do bochs 4- Rodar o bochs Vamos executar os passos acima via console: obs.: O primeiro passo deve ser feito com o bximage que vem junto ao bochs Nele voce seleciona que quer criar uma imagem de um floppy de 1.44mb com o nome de disk.img, e este arquivo deve estar no diretorio do bootw [s0ul@root tests]$ bximage [s0ul@root tests]$ nasm boots.asm -o boots.bin -fbin [s0ul@root tests]$ bootw boots.bin disk.img :: Abrindo Boot Sector :: Setando como boot file :: Boot signature 0x55AA gravado :: OK.. Boot sector gravado com sucesso [s0ul@root tests]$ Teremos que criar o arquivo de configuração do bochs, vou facilitar para voce vou colocar o codigo de um arquivo de configuração pronto aqui: # ------------------------------------- .bochsrc ----------------------------------------- floppya: 1_44="disk.img", status=inserted # no floppyb ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata1: enabled=0 ata2: enabled=0 ata3: enabled=0 romimage: file=/usr/share/bochs/BIOS-bochs-latest , address=0xf0000 vgaromimage: /usr/share/bochs/VGABIOS-lgpl-latest megs: 4 parport1: enabled=1, file="" # no sb16 boot: floppy floppy_bootsig_check: disabled=0 vga_update_interval: 30000 keyboard_serial_delay: 20000 keyboard_paste_delay: 100000 floppy_command_delay: 50000 ips: 500000 pit: realtime=0 text_snapshot_check: 0 mouse: enabled=0 private_colormap: enabled=0 i440fxsupport: enabled=0 time0: 0 # no ne2k newharddrivesupport: enabled=1 # no loader log: - logprefix: %t%e%d debugger_log: - panic: action=fatal error: action=report info: action=report debug: action=ignore pass: action=fatal keyboard_mapping: enabled=0, map= keyboard_type: mf user_shortcut: keys=none config_interface: textconfig display_library: x #------------------------------------------------------------------------------------------ Ai esta o arquivo de configuração do bochs, salve em um arquivo chamado .bochsrc que é o arquivo padrão que o bochs faz a leitura, e depois rode o bochs, podera dar um erro falando que nao encontro o BIOS-bochs-latest, caso ocorra, basta voce mudar o lugar do arquivo para o local correto ok. Bem, agora voce deve estar pensando " se o boot sector pode conter somente 512 bytes então meu OS nao vai passar disso? 512 bytes? ", claro que nao, bom para proceguir ai é sua escolha, ou procegue construindo seu kernel em C, ou então continua a escrever seu OS em assembly, mostrarei aqui um simples exemplo de como sair de seu boot sector e começar a programar diretamente em seu OS. O que devemos fazer para poder continuar, como nosso boot sector como ja sabemos pode conter somente 512 bytes, neste 512 bytes nos podemos fazer uma simples função que carregue um arquivo na memoria ( kernel ) e o execute, ou seja, passe o controle para ele, onde este arquivo podera ser do damanho que ele quizer, a função para carregar setores na memoria é a função 0x02 da int 13 que é uma interrupção da bios, esta função funciona assim: ah = 0x02 al = numero de setores a carregar ch = numero do cilindro cl = numero do setor dh = numero da cabeça dl = Numero do drive ( 0 = A, 1 = B, 0x80 = drive 0, 0x81 = drive 1 ... etc ) es:bx = ponteiro para o buffer Com estas informações ja podemos criar ou melhor recriar nosso boot sector, agora com o objetivo de carregar o proximo setor na memoria e pular para este local, vamos escrever o codigo ;------------------------------- boots2.asm ---------------------------------------- ; Boot Sector para tutorial sobre osdevel por s0ul ; compile: nasm boots2.asm -o boots2.bin -fbin [ORG 0x7C00] ; onde o codigo começara [BITS 16] ; lembre estamos em real mode ( 16 bits ) main: mov si,mstart ; si aponta para mensagem call printstr ; Printa na tela call loadsector ; Carrega os setores na memoria jmp $ ; Loop infinito printstr: mov ah,0x0E mov bl,0x07 mov bh,0x0 .loop: lodsb or al,al jz .endloop int 0x10 jmp .loop .endloop: ret loadsector: mov ax,0x500 ; Move ax para o endereço da memoria onde sera carregado mov es,ax ; ES = AX xor bx,bx ; zera bx mov dh,bl ; zera dh mov ch,bl ; zera ch mov cl,0x02 ; CL = 2 mov al,0x01 ; AL = 1 mov ah,0x02 ; AH = 2 int 0x13 ; chama a função da BIOS jz .loaded ; Se tudo esta correto pula call error ; Senao chama o erro .loaded: jmp 0x500 ; Pula para o começo do codigo carregado error: ; Função de erro, printa mensagem na tela, depois entra em loop infinito mov si,loaderror call printstr jmp $ mstart db 'Welcome to my OS',13,10,0 loaderror db 'Error: Invalid Disk...',13,10,0 times 510-($-$$) db 0 ;dw 0x55,0xAA ;----------------------------------- FIM -------------------------------------------- Como voce pode perceber este boots acima le o segundo setor do floppy disk, o carrega na memoria e entao pula para o inicio de seu codigo, claro que isto é somente um exemplo se voce esta pensando em aperfeiçoar seu OS, voce tera que ler mais setores, isto vai depender do tamanho de seu OS, e nao para ai, a muitas coisas a aprender.. vamos continuar. Agora vamos continuar a criar nosso OS, o codigo a seguir é o que vai ser carregado pelo boots2.. vamos la. Este codigo apenas mostra uma mensagem na tela e fica em loop, ele usa a função 0x13 e 0x03 da int 0x13 que como ja sabemos é da bios, vamos ver como estas funções trabalham ah = 0x13 - Write String al = modo de escrita bh = numero da pagina de video bl = atributo cx = tamanho da string dh = coordenada x dl = coordenada y es:bp = ponteiro para string ah = 0x03 - Read Cursor Position bh = Pagina de video ;----------------------------------- posboot.asm ------------------------------------------- ; Simples exemplo para tutorial sobre osdevel por s0ul ; compile: nasm posboot.asm -o posboot.bin -fbin main: mov ah,0x03 ; AH = 3 ( Read cursor position ) xor bh,bh ; BH = 0 ( Numero da pagina ) int 0x10 ; Executa a função mov ah,0x13 ; AH =0x13 ( Write string ) mov cx,0x10 ; Parametros.... mov bp,msg ; .... mov bh,0x00 ; ... mov bl,0x07 ; ...... mov ah,0x13 ; ..... mov al,0x01 ; ...... int 0x10 ; Enfim executa a função looop: jmp $ ; Entra em loop infinito msg db "We are in Loop",13,10 times 512-($-$$) db 0 ;dw 0x55,0xAA ;---------------------------------------- FIM ----------------------------------------------- Bom, salve como posboot.asm e vamos ao console e execute os comandos [s0ul@root tests]$ nasm boots2.asm -o boots2.bin -fbin [s0ul@root tests]$ nasm posboot.asm -o posboot.bin -fbin Feito isto os arquivos boots2.bin e posboot.bin serão criados, agora para colocarmos os dois em um floppy o nosso Boot Writer nao vai dar conta, pois ele so coloca no floppy o boot sector, entao vamos criar um Boot Write v2, agora com a opção de colocar mais um arquivo no segundo setor do floppy, vamos la. //--------------------------------- Boot Write v2 --------------------------------------------- // Boot Write v2 para tutorial sobre osdevel por s0ul // compile: gcc bootwriter2.c -o bootw2 // ./bootw #include #include int main(int argc,char *argv[]) { char bufb[512]; int fdisk,bdisk; if (argc < 4) { printf("\n\n BootWriter v2 by s0ul\n"); printf(" use: %s \n\n",argv[0]); exit(0); } printf("\n\n:: Abrindo Boot Sector"); bdisk = open(argv[1],O_RDONLY); printf("\n:: OK"); read(bdisk,bufb,510); close(bdisk); printf("\n:: Setando como boot file"); bufb[510] = 0x55; bufb[511] = 0xAA; printf("\n:: Boot Signature 0x55AA gravado"); fdisk = open(argv[3],O_RDWR); lseek(fdisk,0,SEEK_SET); write(fdisk,bufb,512); printf("\n:: Gravando boots: sector1 posboot: sector2"); bdisk = open(argv[2],O_RDONLY); read(bdisk,bufb,512); close(bdisk); lseek(fdisk,513,SEEK_SET); write(fdisk,bufb,512); printf("\n:: OK.. Setores gravados com sucesso\n\n"); close(fdisk); } ;------------------------------------------ FIM ------------------------------------------------ Agora que ja temos o nosso bootw2 vamos ao console e gravar os dados no floppy [s0ul@root tests]$ gcc bootwriter2.c -o bootw2 [s0ul@root tests]$ ./bootw2 BootWriter v2 by s0ul use: ./bootw2 [s0ul@root tests]$ ./bootw2 boots2.bin posboot.bin /dev/fd0 :: Abrindo Boot Sector :: Setando como boot file :: Boot Signature 0x55AA gravado :: Gravando boots: sector1 posboot: sector2 :: OK.. Setores gravados com sucesso [s0ul@root tests]$ Ai esta pronto, agora se voce quizer criar o disk.img para usar com o bochs digite em seu console: [s0ul@root tests]$ ./bootw2 boots2.bin posboot.bin disk.img :: Abrindo Boot Sector :: Setando como boot file :: Boot Signature 0x55AA gravado :: Gravando boots: sector1 posboot: sector2 :: OK.. Setores gravados com sucesso [s0ul@root tests]$ bochs ----------- ----- ---------------------------------------------------------- ---- ----------- Pronto agora é so testar o seu OS, claro que é bem simples, tem muito o que aprender ainda, aconselho a voce agora consultar tutoriais sobre sistemas de arquivos, partições, enfim, tudo que se relaciona a um OS, pois se voce esta criando um do zero, voce tera que fazer tudo na mão, desde sua primeira mensagem, como seu proprio sistema de arquivos, ou até, futuramente seu proprio ambiente grafico, ensinei aqui o basico, acho que agora voce pode seguir sozinho com suas proprias pernas.. ----------- ----- ---------------------------------------------------------- ---- ----------- Bom pessoal, vou me despedindo espero que voces tenham gostado deste tutorial, vai ser complicado para voce entender tudo de uma vez, leia um pouco depois voce volta no que nao entendeu, ou entao me procure que eu terei o maior prazer em ajuda-lo com qualquer duvida que voce tenha. Um abraço. ----------- ----- ---------------------------------------------------------- ---- -----------