Você está na página 1de 7

Universidade Luterana do Brasil Projeto de Sistemas Operacionais

UNIDADE 05 - NANOSO – O MENOR SISTEMA


OPERACIONAL DO MUNDO

1 INTRODUÇÃO
O desenvolvimento de um sistema operacional é frequentemente citado como uma tarefa árdua e
complexa. Trata-se, naturalmente, de um exercício de programação que exige, pelas funções que um sistema
operacional exerce, muito mais conhecimentos do hardware do que o desenvolvimento de aplicações. Na maioria
das vezes os sistemas operacionais devem funcionar de forma concorrente, viabilizando a execução de processos
concorrentes que necessitam de recursos gerenciados pelo sistema operacional para executar. Este é outro fator que
contribui para aumentar a complexidade de um sistema operacional.
Naturalmente o sistema operacional será tão mais complexo quanto maior for o número de serviços que ele
disponibilizar para as aplicações e quanto mais sofisticados forem estes serviços.
Iniciar o desenvolvimento de um sistema operacional, uma idéia que com certeza já passou pela cabeça de
muitos programadores, não é, no entanto, necessariamente uma tarefa tão difícil quanto pode parecer num primeiro
momento. É exatamente isto que se pretende demonstrar com esta aula.
Através do desenvolvimento de um sistema operacional de dimensões mínimas, o objetivo será mostrar
que é possível iniciar o desenvolvimento de um sistema operacional seguindo uma estrutura e aprimorando-o
gradualmente com a adição de novos serviços. Este sistema operacional, chamado de nanoSO (nanoSistema
Operacional) possui apenas duas chamadas de sistema e pode (talvez) ser considerado o menor sistema operacional
do mundo. Levando isto em consideração, as decisões que nortearam o seu projeto foram sempre no sentido de
fazê-lo o menor possível.

2 PLANEJAMENTO
Há muitas decisões que devem ser tomadas no início do desenvolvimento do projeto de um sistema
operacional. Por exemplo:
• quais serão seus componentes?
• quais as funções de cada componente?
• qual será a sua estrutura?
• que chamadas ele deverá possuir?
• ele permitirá a execução concorrente?
• utilizará serviços do BIOS (Basic Input Output System)?
• ele funcionará em modo protegido?
• que linguagens utilizar (linguagem de montagem, C, ...)?
• como e em qual sistema operacional ele será compilado?
• será possível que ele se auto-recompile?
• por onde começar?
Muitas destas perguntas serão respondidas ao longo deste texto, naturalmente, para o nanoSO, cujo
objetivo, é bom lembrar, é ser o menor sistema operacional possível.

Autor: Roland Teodorowitsch (23/10/2013) 1


Universidade Luterana do Brasil Projeto de Sistemas Operacionais

3 COMPONENTES
Para o desenvolvimento de um sistema operacional pode-se considerar que ele deve ter no mínimo dois
componentes ou partes:
• um setor de inicialização: responsável pelo carregamento da imagem do sistema operacional; e
• uma imagem: que corresponde ao código do sistema operacional propriamente dito.
Conforme o porte do sistema operacional, depois que a imagem for carregada, outros componentes
poderão ser utilizados e ativados.

3.1 Setor de Inicialização


O setor de inicialização (boot sector) de um sistema operacional é um dos componentes que menos
aparecem, pois ele executa o seu serviço no início da execução, carregando a imagem do sistema operacional, e
depois não é mais executado. Este setor corresponde ao primeiro setor de um disco flexível ou o primeiro setor de
uma partição de um disco rígido e tem, em geral, 512 bytes de tamanho.
Quando o computador é ligado, após o POST (Power On Self Test), o BIOS carrega o primeiro setor do
dispositivo habilitado para inicialização, sempre no endereço 0x07c00 (ou 0000:7C00 ou 07C0:0000), e inicia a
sua execução. Este é o setor de inicialização que carregará a imagem do sistema operacional.
A linguagem normalmente utilizada para desenvolver o setor de inicialização é a linguagem de montagem
(assembly), mas há alternativas como a linguagem Bootlib (TEODOROWITSCH, 2000). Bootlib é uma linguagem
de alto nível desenvolvida para tornar a implementação de setores de inicialização e gerenciadores de partida mais
simples. Basicamente a linguagem incorpora uma biblioteca que facilita o desenvolvimento deste tipo de código.
A Figura 1 apresenta o setor de inicialização do nanoSO, codificado em Bootlib.

/* Arquivo: boot.bl */
boot(size=512,signature,segment=0x07c0)
{
fat(oem="nanoSO",volume="BOOTDISK",disk=FD1440);
setstack(0x0000,0x7c00);
setcolor(0x07);
putstr("Carregando nanosSistema Operacional Vs 1.0...");
readdisk_chs(0x00,0,1,16,1,0x07e0,0x0000);
putch('\n');
jump(0x07e0,0x0000);
}

Figura 1 – Programa em Bootlib para carregamento de uma imagem com um setor

No programa da Figura 1, define-se que:


• o tamanho do setor de inicialização será de 512 bytes ( size=512);
• o setor conterá, nos dois últimos bytes, a assinatura padrão para setores de inicialização ( signature);
• o setor será colocado no segmento de código 0x07c0 ( segment=0x07c0);
• o setor será gerado de forma a ser compatível com o sistema de arquivos FAT do MS-DOS:
fat(oem="nanoSO",volume="BOOTDISK",disk=FD1440);
• a pilha do sistema terá segmento igual a 0x0000 e deslocamento igual a 0x7c00:
setstack(0x0000,0x7c00);
• a cor para impressão de mensagens será 0x07:
setcolor(0x07);
• será exibida uma mensagem de carga:
putstr("Carregando nanosSistema Operacional Vs 1.0...");
• será lido do disco 0x00, no cilindro 0, cabeça 1, número relativo de setor 16, um (1) setor, que será
colocado no endereço de memória formado pelo segmento 0x07e0 e pelo deslocamento 0x0000:
readdisk_chs(0x00,0,1,16,1,0x07e0,0x0000);
• a execução será iniciada no endereço formado pelo segmento 0x07e0 e pelo deslocamento 0x0000:
jump(0x07e0,0x0000);
É importante observar que este setor de inicialização exige que a imagem do sistema operacional seja
colocada no cilindro 0, cabeça 1, setor relativo 16. Esta posição corresponde exatamente ao primeiro setor da área
de dados de um disco de 3 1/2 polegadas, 1,44MB, formatado com o sistema de arquivos FAT 12. Para garantir

Autor: Roland Teodorowitsch (23/10/2013) 2


Universidade Luterana do Brasil Projeto de Sistemas Operacionais

que a imagem do sistema operacional esteja nesta posição, basta formatar um disco, ou utilizar um disco vazio, e
fazer com que o primeiro arquivo copiado neste disco seja o arquivo que contém a imagem do sistema operacional.
Para compilar o programa boot.bl (da Figura 1) e gerar um arquivo chamado boot.bin são necessários
os passos especificados na Figura 2. Inicialmente o compilador Bootlib gera um código em linguagem de
montagem que deve ser montado (usando tasm), ligado (usando tlink) e convertido para um binário puro
(usando exe2bin), sem cabeçalho.

bootlib -o boot.asm boot.bl


tasm /zn boot
tlink boot
exe2bin boot boot.bin

Figura 2 – Passos para a compilação do setor de inicialização

Para colocar o arquivo boot.bin no primeiro setor do disco flexível, pode-se utilizar o programa
bootcopy.exe que se encontra no diretório de executáveis que acompanha o código-fonte do nanoSO. A
execução deste programa é simples, não necessitando de nenhum parâmetro. Ele sempre tentará transferir o
arquivo boot.bin para o primeiro setor do disco.

3.2 Imagem
A imagem corresponde ao código do sistema operacional propriamente dito. Contendo, no mínimo: código
de inicialização (para acerto dos vetores de interrupção, ajuste da pilha do sistema, etc.), um processo inicial e
chamadas de sistema. A Figura 3 mostra a estrutura do nanoSO.

Figura 3 – Estrutura do nanoSO

O sistema operacional pode ser desenvolvido usando chamadas e serviços do BIOS ou pode ter seus
próprios controladores de dispositivos. O desenvolvimento de controladores de dispositivos torna o sistema
operacional maior e mais complexo, pois o sistema deverá ter código para controlar todos os dispositivos. Com isto
consegue-se contornar as limitações que existem nas chamadas do BIOS. O nanoSO utilizará o BIOS para
implementar suas duas únicas chamadas de sistema: leitura do teclado e impressão no vídeo. Quando o sistema
operacional utilizar o BIOS na implementação de suas chamadas de sistema, é recomendável que os processos
utilizem apenas chamadas de sistema e não chamadas do BIOS. Isto torna o código do nível de aplicação mais
portável, pois o BIOS é específico de máquinas do padrão IBM/PC.
As chamadas de sistema são serviços que o sistema operacional disponibiliza para facilitar o
desenvolvimento de aplicações. Em geral, cada serviço está associado a um número. Por exemplo, no nanoSO, os
serviços disponíveis são:
• serviço 0: leitura de caracter;
• serviço 1: impressao de caracter.
O sistema operacional desvia um vetor de interrupção (na faixa de 0x20 até 0xFF) p/ uma rotina sua que
receberá em AH o número do serviço e que executará a solicitação da aplicação. No caso do nanoSO, o vetor de
interrupção adotado para implementar o ponto de entrada do código que executa as chamadas de sistema é o vetor
0x22.
Para executar a chamada de sistema, a aplicação deve informar no registrador AH o número do serviço e,

Autor: Roland Teodorowitsch (23/10/2013) 3


Universidade Luterana do Brasil Projeto de Sistemas Operacionais

conforme o caso, outros parâmetros em outros registradores. Resultados também são retornados em registradores.
A Figura 4 mostra um exemplo de código para leitura de um caracter no nanoSO (sendo que a tecla lida
estará no registrador AL), seguido de um exemplo para impressão de caracter (no caso o caracter 'A', cujo código
ASCII é 65).

; Leitura de caracter
MOV AH,0
INT 22h

; Escrita de caracter
MOV AL, 65
MOV AH,1
INT 22h

Figura 4 – Exemplo de execução de chamadas de sistema no nanoSO

Em geral o código da imagem de um sistema operacional é implementado em linguagem de alto nível, com
uma pequena camada de serviços básicos implementados em linguagem de montagem. A versão inicial da imagem
do nanoSO foi totalmente implementada em linguagem de montagem, uma vez que o seu código é extremamente
pequeno. A Figura 5 mostra o código-fonte da imagem do nanoSO.

Autor: Roland Teodorowitsch (23/10/2013) 4


Universidade Luterana do Brasil Projeto de Sistemas Operacionais

; Arquivo: nanoSO.asm
; Autor: Roland Teodorowitsch
;

_TEXT segment byte public 'CODE'


assume cs:_TEXT

_main proc near

; desabilita interrupções
cli

; define a pilha
mov ax,7c00h
mov sp,ax
mov ax,0
mov ss,ax

; desvia a interrupção 22h


xor ax,ax
mov ds,ax
mov ax,offset _scall
mov ds:[22h*4],ax
mov ax,07e0h
mov ds:[22h*4+2],ax

; habilita interrupções
sti

; laço principal
laco: mov ah,0
int 22h
mov ah,1
int 22h
jmp laco

_main endp

_scall proc near

cmp ah,0
jnz nao_eh_servico_0

servico_0:
mov ah,10h
int 16h
iret

nao_eh_servico_0:
cmp ah,1
jnz tambem_nao_eh_servico_1

servico_1:
mov ah,0eh
xor bh,bh
int 10h
iret

tambem_nao_eh_servico_1:
iret

_scall endp

_TEXT ends

end

Figura 5 – Código-fonte da imagem do nanoSO

4 COMPILAÇÃO E EXECUÇÃO DO NANOSO


Para compilação e execução do nanoSO pode-se usar simplesmente o camando make (que deve estar em
algum diretório que faça parte da variável PATH do sistema). Basta entrar no diretório de fontes do nanoSO e
digitar:
• make: para compilar;
• make run: para compilar (se ainda não tiver sido compilado) e executar o sistema na máquina virtual
Bochs.
A Figura 6 apresenta o código do arquivo Makefile (usado pelo comando make).

Autor: Roland Teodorowitsch (23/10/2013) 5


Universidade Luterana do Brasil Projeto de Sistemas Operacionais

# Arquivo: Makefile
# Autor: Roland Teodorowitsch
#

# ---- all ---------------------------------------


all: nanoSO.img

# ---- nanoSO.img --------------------------------


nanoSO.img: boot.bin nanoSO.bin
@mkfpimg boot.bin nanoSO.bin nanoSO.img

# ---- boot.bin ----------------------------------


boot.asm: boot.bl
@bootlib -o boot.asm boot.bl

boot.obj: boot.asm
@tasm /zn boot

boot.exe: boot.obj
@tlink boot

boot.bin: boot.exe
@exe2bin boot boot.bin

# ---- nanoSO.bin --------------------------------


nanoSO.obj: nanoSO.asm
@tasm /zn nanoSO,,,

nanoSO.exe: nanoSO.obj
@tlink /s nanoSO,,,,

nanoSO.bin: nanoSO.exe
@exe2bin nanoSO nanoSO.bin

# ---- clean -------------------------------------


clean:
@if exist bootlib.str del bootlib.str
@if exist boot.asm del boot.asm
@if exist *.obj del *.obj
@if exist *.bin del *.bin
@if exist *.exe del *.exe
@if exist *.map del *.map
@if exist *.xrf del *.xrf
@if exist *.lst del *.lst
@if exist *.img del *.img
@if exist bochsout.txt del bochsout.txt

# ---- install ------------------------------------


install: boot.bin nanoSO.bin
@bootcopy boot.bin
@if exist a:\nanoSO.bin del a:\nanoSO.bin
@copy nanoSO.bin a:\ > nul

# ---- run ----------------------------------------


run: all
@-bochs -q -f nanoSO.bochsrc > nul

Figura 6 – Makefile para o nanoSO

5 EXERCÍCIOS
1. Os antigos discos flexíveis de 5,25" com capacidade de 1.2MB possuem: 80 trilhas por face, 2 superfícies de
gravação e 15 setores por trilha. Considere um sistema de arquivos FAT12 instalado neste disco e calcule:
a) em que setor absoluto do disco inicia a área de dados deste sistema de arquivos;
b) a qual cilindro (C), cabeça (H) e setor da trilha (S) corresponde o início da área de dados deste sistema de
arquivos.
Considere que: os agrupamentos (clusters) possuem 1 setor; existem 2 FATs; o número máximo de entradas
no diretório raiz seja de 224.

2. Considerando o código do nanoSO apresentado inicialmente nesta aula. Modifique-o para que sejam
reconhecidas as teclas RETURN ou ENTER (que funcionará imprimindo os caracteres LINE FEED e
CARRIAGE RETURN do BIOS) e ESC que reinicializará o nanoSO. Para reinicializar o sistema basta
executar a interrupção 19h, ou seja, a instrução int 19h em linguagem de montagem.

Autor: Roland Teodorowitsch (23/10/2013) 6


Universidade Luterana do Brasil Projeto de Sistemas Operacionais

REFERÊNCIAS
TEODOROWITSCH, Roland. Bootlib: uma linguagem para definição de setores de inicialização. In: XXVI
CONFERENCIA LATINOAMERICANA DE INFORMÁTICA, Atizapán de Zaragoza: Tec de Monterrey, 2000.

Autor: Roland Teodorowitsch (23/10/2013) 7

Você também pode gostar