Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Oficina
Sex
25
Mai
2007
20:08
MÓDULO 3 do SO Numaboa
Um dos requisitos para poder começar a pensar em criar um sistema operacional é conhecer a linguagem de
Ferramentas
NASM - o compilador Assembly. As versões mais atualizadas e a documentação estão disponíveis para download
no site oficial do NASM. A versão 0.98.39 para Windows está disponível aqui na Aldeia na seção de downloads
(Informática / Compiladores).
helpPC - Onde você encontra todas as referências imagináveis. Faça o download do helppc versão 2.1 aqui na
Aldeia (downloads Informática / Referências e Manuais) ou procure-o pela Internet.
A linguagem Assembly
Todo processador possui um conjunto de instruções próprio. É como se fosse uma "linguagem" embutida dentro da
CPU. Cada instrução possui um código operacional e realiza determinada tarefa dentro do processador utilizando
seus registradores. Estes códigos são identificados por números. Na linguagem Assembly estes números são
transformados nos chamados mnemônicos para facilitar a programação. Assim, por exemplo, o número
hexadecimal B2 (178 decimal) corresponde a MOV DL em Assembly. MOV é o mnemônico de MOVer e DL é o
byte menos significativo do registrador DX.
1 de 10 2/5/2013 11:57
Aldeia Numaboa - 3. Curso relâmpago de Assembly http://www.numaboa.com.br/informatica/oficina/123-so/735-curso-de-...
Os registradores
Registradores são áreas de trabalho especiais dentro do microprocessador projetadas para trabalharem com
códigos operacionais. São uma espécie de "memória" da CPU e servem para armazenar informações
temporariamente.
Os registradores mais utilizados são 8, chamados de uso geral. Destes, usaremos com frequência apenas 4: AX,
BX, CX e DX. Estes registradores podem armazenar 16 bits, ou seja, 2 bytes (nas máquinas de 32 bits, assim
chamadas porque os registradores da sua CPU podem armazenar 32 bits, estes mesmos registradores recebem
os nomes de EAX, EBX, ECX e EDX).
Não é à toa que os registradores receberam estes nomes: AX é também o Acumulador, BX é a Base, CX é o
Contador e DX vem de Dados. Os nomes derivam do uso mais frequente destes registradores.
Com Assembly podemos acessar diretamente os dois bytes (2 bytes = word) dos registradores de 16 bits ou
podemos acessar diretamente o byte mais significativo ou superior (high) ou menos significativo ou inferior (low).
Assim, por exemplo, podemos usar instruções com AX (word), AH (byte superior de AX) ou AL (byte inferior de
AX), com BX, BH ou BL, etc.
É claro que existem mais registradores, mas não precisaremos deles por enquanto.
A instrução MOV
Esta instrução, uma das mais usadas, copia dados de um local para outro e o mnemônico deriva de MOVer. Veja
alguns exemplos de uso:
mov ax, 1 ; Move 1 para AX, ou seja, AX = 1
mov bx, ax ; Move o valor de AX para BAX, ou seja, BX = AX
A instrução INT
A instrução INT gera uma interrupção de software. O DOS e a BIOS fornecem muitas funções úteis que podem ser
acessadas através desta instrução:
INT 0x10 ; chama uma interrupção 10hex de software
Um pequeno programa
Este é um programa extremamente simples:
mov ax, 0x4C00 ; AH = 0x4C, AL=0
int 0x21 ; a interrupção de software 0x21 é chamada
Este programa nada mais faz do que... terminar. Está na hora de usar o helpPC para esclarecer este assunto:
1. Inicie o helpPC - uma tela chamada "Main Topic Menu" será mostrada.
2. Destaque o item de menu "Interrupt Services DOS-BIOS-EMS-Mouse" e tecle Enter.
3. Destaque o item "DOS Functions" e tecle Enter.
4. Escolha INT 21,4C
O helpPC nos informa que a INT 21,4C corresponde a Terminate Process With Return Code, ou seja, Termine o
Processo com Código de Retorno. Também informa que AH precisa conter o valor 4C e que AL precisa conter o
2 de 10 2/5/2013 11:57
Aldeia Numaboa - 3. Curso relâmpago de Assembly http://www.numaboa.com.br/informatica/oficina/123-so/735-curso-de-...
código de retorno (do arquivo de lote). Além disto, a instrução não tem valor de retorno.
Portanto, para usar esta instrução, basta preparar AH e AL com os parâmetros exigidos e chamar a interrupção.
Com isto terminamos o programa... e com o método aprovado! Se quiser testar este programa, salve o código
fonte como teste1.asm, compile-o com o NASM com nasm -o teste1.com teste1.asm para obter teste1.com
Variáveis
As variáveis no Assembly são um pouco diferentes quando comparadas com as de outras linguagens de
programação. No Assembly podemos inserir dados diretamente no programa com DB, DW e DD (onde
B=byte=8bits, W=word=16 bits e D=duplo word=32 bits). Além disto, podemos atribuir marcadores para os dados
para identificá-los por nomes - estão aí as nossas variáveis!
varb db 0 ; 1 byte chamado "varb" é inserido
varw dw 0 ; 1 word chamado "varw" é inserido (1 word=2 bytes)
vard dd 0 ; 1 duplo chamado "vard" é inserido (1 double=4 bytes)
3 de 10 2/5/2013 11:57
Aldeia Numaboa - 3. Curso relâmpago de Assembly http://www.numaboa.com.br/informatica/oficina/123-so/735-curso-de-...
Entrada de teclado
Ponha novamente o helpPC em ação e procure pela interrupção do DOS INT 21,A. A explicação parece um pouco
complicada, mas não se preocupe. DS:DX deve conter um ponteiro para um buffer. Este buffer contém 3 áreas:
max - o número máximo de caracteres que devem ser lidos, count - o número de caracteres retornados e buffer - a
área de entrada. O código comentado vai facilitar as coisas:
[ORG 0x100]
4 de 10 2/5/2013 11:57
Aldeia Numaboa - 3. Curso relâmpago de Assembly http://www.numaboa.com.br/informatica/oficina/123-so/735-curso-de-...
Saltos
Saltos, os famosos jump, desviam a linha de execução. Geralmente são condicionais, do tipo "se alguma coisa,
então salte para...", mas existe também uma instrução de salto incondicional. Os mais comuns são:
JA Salte se acima (above)
JAE Salte se acima ou igual (above or equal)
JB Salte se abaixo (below)
JBE Salte se abaixo ou igual (below or equal)
JE Salte se igual (equal)
JMP Salto incondicional
JNA Salte se não acima (not above)
JNB Salte se não abaixo (not below)
JNE Salte se não igual (not equal)
JNZ Salte se não zero (not zero)
JZ Salte se zero
Como a maioria dos saltos são condicionais, é claro que precisamos de uma instrução que faça comparações. É a
CMP, mnemônico de CoMParar (ou CoMPare). Observe no código abaixo como criar um loop com uma instrução
de salto. Este programa imprime NumaBoa cinco vezes e termina:
[ORG 0x100]
5 de 10 2/5/2013 11:57
Aldeia Numaboa - 3. Curso relâmpago de Assembly http://www.numaboa.com.br/informatica/oficina/123-so/735-curso-de-...
Funções
As funções em Assembly são como os marcadores só que, ao invés de serem acessadas através de saltos, são
chamadas e precisam ter uma instrução de retorno. Também é possível enviar parâmetros para as funções através
de registradores ou da pilha. As funções são úteis quando há tarefas repetitivas. Observe um esqueleto de uma
função:
[ORG 0x100]
call func ; Chama a função
inicio:
mov ah, 9 ; Serviço de impressão da INT 21
mov dx, msg1 ; Imprime "Escreva alguma coisa: "
int 0x21
tecla:
mov ah, 0x1 ; Serviço de rastrear uma tecla
int 0x21
6 de 10 2/5/2013 11:57
Aldeia Numaboa - 3. Curso relâmpago de Assembly http://www.numaboa.com.br/informatica/oficina/123-so/735-curso-de-...
termina:
mov al, '$' ; Põe caracter terminador '$' em AL
mov bl, [count] ; Põe número de teclas digitadas em BL
mov bh, 0 ; Zera o byte alto de BX
mov [data+bx], al ; Adiciona '$' no final do buffer
fecha:
mov ax, 0x4c00 ; Serviço para terminar programa
int 0x21
7 de 10 2/5/2013 11:57
Aldeia Numaboa - 3. Curso relâmpago de Assembly http://www.numaboa.com.br/informatica/oficina/123-so/735-curso-de-...
A Pilha
A pilha é uma área especial de memória dentro do processador. Informações guardadas na pilha com PUSH são
colocadas no topo. Quando informações são tiradas da pilha com POP, estas também são tiradas do topo. Isto
resulta numa regra simples: os últimos dados que entram na pilha são os primeiros a sair. A pilha é muito utilizada
pelas rotinas dos códigos operacionais do computador. Por exemplo, toda instrução CALL põe o endereço da
instrução de chamada na pilha para que a instrução de retorno RETN saiba para onde saltar para voltar ao ponto
de chamada.
Veja um pouco de código usando PUSH e POP e observe como os valores dos registradores AX e BX foram
trocados com o auxílio da pilha:
mov ax, 123
mov bx, 456
Segmentos e Deslocamentos
Este é o tipo de assunto que no início dá nó na cabeça de qualquer um, mas, uma vez entendido, facilita muito a
programação Assembly.
Segmentos
Quando as máquinas foram melhoradas, a memória do computador (aquelas "tripinhas" de chips que a gente
espeta na placa-mãe) passou a armazenar vários megabytes - muitas vezes o maior número que conseguimos
obter com 16 bits. Num sistema de 16 bits, o maior número que conseguimos obter é 1111 1111 1111 1111 em
binário ou 65535 em decimal. Este número corresponde a 64 Kb, muito longe dos megabytes. A questão era: o
que fazer para acessar posições de memória acima de 65535?
Foi daí que o pessoal resolveu "lotear" a memória em segmentos e, adivinhe, cada segmento com 65536 bytes (de
0 a 65535). Para acessar qualquer ponto da memória, passou-se a usar um duplo endereço: o número do
segmento e a posição dentro deste segmento. Com os segmentos colocados um após o outro, as posições de
memória ficariam da seguinte forma:
Segmento 0 começa na posição 0 e vai até 65535
Segmento 1 começa na posição 65536 e vai até 131071
...
Acontece que nem sempre os dados colocados na memória, como programas, dados e a pilha, ocupavam
segmentos inteiros. Como resultado, a memória - chipzinhos caros pra caramba - pareciam um queijo suiço cheio
8 de 10 2/5/2013 11:57
Aldeia Numaboa - 3. Curso relâmpago de Assembly http://www.numaboa.com.br/informatica/oficina/123-so/735-curso-de-...
de buracos. Resolveu-se então sobrepor os segmentos usando uma distância entre eles de 16 bytes. Desta forma,
as posições de memória foram loteadas assim:
Segmento 0 começa na posição 0 e vai até 65535
Segmento 1 começa na posição 16 e vai até 65551
...
Segmento 100 começa na posição 1600 e vai até 67135
...
Segmento X começa na posição X*16 e vai até X*16 + 65535
Deslocamento
O deslocamento (offset) é um endereço relativo porque depende do segmento. Nada mais é do que a posição de
determinado byte dentro das 65536 posições possíveis. Lembre-se de que as posições são numeradas de 0 a
65535, o que dá o total de 65536 posições. Lembre-se também que o deslocamento nunca pode ser maior do que
65535 porque... não conseguimos um número maior do que este com 16 bits.
O deslocamento é a segunda porção do duplo endereço de uma posição de memória, geralmente indicada por
Segmento:Deslocamento. Para facilitar, vamos a um exemplo prático:
Endereço 1234:5678 => Segmento 1234 e Deslocamento 5678
Se bagunçarmos estes registradores, os resultados podem ser catastróficos (nem preciso explicar porque
Para evitar que inadvertidamente se mude os valores destes registradores, não existem instruções que façam
alterações diretas - os valores só podem ser alterados indiretamente, forçando a atenção dos programadores.
Veja um exemplo:
mov ax, 1000 ; AX = 1000
mov ds, ax ; Altera o número do segmento para 1000
inc ax ; Incrementa AX
mov [ds:32], ax ; Põe valor de AX no endereço 1000:0032
; - o endereço é 16032
9 de 10 2/5/2013 11:57
Aldeia Numaboa - 3. Curso relâmpago de Assembly http://www.numaboa.com.br/informatica/oficina/123-so/735-curso-de-...
Considerações finais
Este foi o curso de Assembly mais rápido que consegui dar na minha vida. Contém o mínimo necessário para
poder se aventurar nesta linguagem de baixo nível. Se você conseguiu acompanhá-lo (espero que sim), então o
caminho para criar seu próprio sistema operacional (além de milhões de outras coisas) está aberto. A linguagem
Assembly é rápida, eficiente e direta. O código pode parecer longo, mas os programas resultantes são
espantosamente pequenos porque o código compilado é extremamente enxuto. E nada supera a deliciosa
10 de 10 2/5/2013 11:57