Anda di halaman 1dari 119

Introdução ao NASM e a

programação em ambiente Linux

• Linux Boot Time Programming – Uma Primeira


Visão
• Modos de Operação dos Processadores da família
x86 atuais:

• Modo Real
• Modo Protegido
• Modo Virtual
• Modo de Gerenciamento
Introdução ao NASM e a
programação em ambiente Linux

• Linux Boot Time Programming – Uma Primeira


Visão
• Modos de Operação dos Processadores da família
x86 atuais:

• Modo Real
• Modo Protegido
• Modo Virtual
• Modo de Gerenciamento
• Na inicialização, o processador está no Modo Real
Introdução ao NASM e a
programação em ambiente Linux

• Linux Boot Time Programming – Uma Primeira


Visão
• Preparação para mudar para Modo Protegido:
• Preparar a Global Descriptor Table
• Armazenar código em local apropriado, pois quando
houver a mudança para o modo protegido os endereços
físicos serão gerados de maneira completamente diferente.
• Prepara a Interrupt Descriptor Table (IDT), pois os
vetores da IDT são de 8 bytes e os vetores da tabela de
vetores de interrupção do DOS são de apenas 4 bytes.
• Executar o código de mudança para o modo protegido.
Introdução ao NASM e a
programação em ambiente Linux

• Linux Boot Time Programming – Uma Primeira


Visão
• Preparação para mudar para Modo Protegido:
• Preparar a Global Descriptor Table
• O Processador tem um registrador de base e um de limite
para a Global Descriptor Table. Estes registradores são
carregados com a instrução LGDT mem.
• mem é o endereço base de uma região de 6 bytes que
armazena: 2 bytes de limite + 4 bytes de endereço base
para Global Descriptor Table.
Introdução ao NASM e a
programação em ambiente Linux

• Linux Boot Time Programming – Uma Primeira


Visão
• Preparação para mudar para Modo Protegido:
• Preparar a Global Descriptor Table
• Suponha que queiramos definir uma Global Descriptor
Table com 10 descritores e que o endereço base da GDT é
10000H.
• Como cada descritor tem 4 palavras (8 bytes), a GDT terá
80 bytes (50H). Portanto, o limite é 80-1= 79 (50H – 1H =
4FH).
Introdução ao NASM e a
programação em ambiente Linux

• Linux Boot Time Programming – Uma Primeira


Visão
• Preparação para mudar para Modo Protegido:
• Preparar a Global Descriptor Table
• Desta forma, usaremos uma área de memória para
armazenar estas informações (limite e endereço base).
MOV AX,2000H
MOV DS,AX
MOV AX,4FH
MOV [DS:0],AX ;armazena o limite
MOV EAX,100000H
MOV [DS:2],EAX ; armazena o endereço base
LGDT [DS:0] ; carrega os rgistradores de base e de limite
Introdução ao NASM e a
programação em ambiente Linux

• Linux Boot Time Programming – Uma Primeira


Visão
• Preparação para mudar para Modo Protegido:
• Executa código de mudança para o modo protegido.
• Os processadores da família x86 têm um registrador de
controle denominado CR0. Quando o bit 0 deste
registrador é feito 1, o processador muda para o Modo
Protegido.
MOV EAX,CR0
OR EAX,1
MOV CR0,EAX ; muda para o modo protegido
Introdução ao NASM e a
programação em ambiente Linux

• Linux Boot Time Programming – Uma Primeira


Visão
• Preparação para mudar para Modo Protegido:
• Ao mudar para o Modo Protegido o processador não
inicia a paginação. Tornando o bit 31 do CR0 igual a 1,
faz com que se inicie o processo de paginação.
• 31 - PG = Paginação habilitada
• 30 - CD = Cache Desabilitada
• 29 - NW = No Writethrough
• 15 - WP = Write Protection
• 2 - EM = Emulate Math chip
• 1 - MP = Math chip Present
• 0 - PE = Protect Mode Enable
Programação de Baixo Nível em
Linux

• Programas de Usuário
• Pentium suporta segmentação e paginação
• As versões atuais do Linux suportam apenas
paginação.

Memória
Aplicação e
SO
do Usuário I/O
Programação de Baixo Nível em
Linux
• Task State Segment
24

28 CR3 (PDBR)
32 EIP Task register (TR)
EFLAGS
36
EAX
aponta para o TSS da
40
44 ECX tarefa executada no
EDX
48
EBX
momento.
52
56 ESP
CR3 = Control register
60 EBP
PDBR = Page Diretory
64 ESI
Base Register
68 EDI

...
Programação de Baixo Nível em
Linux

• Paginação
Não é usada nas operações de acesso a I/O.
 Memória Virtual no Linux
Espaço de endereçamento: 0 – 4Gb
0
T1 Mem
4Gb
Sistema
0
de
T2 Paginação
4Gb

0 Disco

Tn
4Gb
Programação de Baixo Nível em
Linux
Visão da Memória
• Paginação de um processo
0
Não é usada nas operações de acesso a I/O.
 Memória Virtual no Linux Espaço
do
Espaço de endereçamento: 0 – 4Gb
Usuário 3Gb
3
Kernel Mem Kernel
4Gb
4Gb
Sistema
0
de
T1 Paginação
3Gb

0 Disco

Tn
3Gb
Programação de Baixo Nível em
Linux
• Paginação
• O espaço de endereçamento é dividido em blocos denominados páginas.
• É comum chamar este espaço na memória física (silicio) de page frames.
• Em máquinas x86 as páginas são de 4096 bytes (4Kb)
• Caso a página não se encontre na memória física, um page fault
(interrupção) ocorre. O serviço desta interrupção efetua a leitura do disco,
o correspondente armazenamento/substituição.

3
Kernel Mem
4Gb Sistema
0 de
T1 Paginação
3Gb

0 Disco
Tn
3Gb
Programação de Baixo Nível em
Linux
• Paginação

• A memória física é dividida em page frames. Dado que cada página tem
4096 byte = 212 =4 Kb = 1000H, toda página inicia em um endereço que
tem 3 zeros.
• O espaço virtual de cada tarefa é também dividido em páginas:
4Gb ÷ 4Kb = (4 × 230) ÷ (4 × 212) = 220 = 1 Megapáginas.
• A área do disco usada para paginação é também dividida em páginas. Esta
área é denominada área de swap. Dado que a maioria dos discos são
formatados em setores de 512 bytes, portanto são necessários 8 setores
para armazenar cada página (8 × 512 = 4096).
A área de memória reservada para o kernel será compartilhada por todas
as tarefas.
Programação de Baixo Nível em
Linux

• Paginação
• Tradução do Endereço (hardwired)

10 bits 10 bits 12 bits Endereço Virtual

CR3
Page Table Table (Page Directory) Page Table 4kb page frame
Programação de Baixo Nível em
Linux

• Paginação
• Exemplo: enderço virtual 801C3400H

1000000000 0111000011 010000000000 Endereço Virtual

400H
200H
1C3H

01234+”000”
Endereço Físico
E4000+”000” + 01234400H

CR3
Page Table Table (Page Directory) Page Table
Programação de Baixo Nível em
Linux

• Paginação
• Entradas das Page (Table) Table

31 12 11 2 1 0
U W P
Endereço da página
S R P

Como cada page frame tem três zeros (000H) na parte inferior do
endereço, podemos definir o endereço usando apenas os 20 bits
mais significativos do endereço.

PP – página presente. Quando em 1, significa que a página está na RAM


Caso PP=0, podemos ter duas situações: a página pode estar no disco (ocorre page fault)
endereço inválido (ocorre segmentation fault).
Programação de Baixo Nível em
Linux

• Paginação
• Entradas das Page (Table) Table

31 12 11 2 1 0
U W P
Endereço da página
S R P

•O fato do espaço de endereçamento do kernel ser compartilhado


por todas as tarefas, pode dar a impressão que a memória do kernel
pode ser usada por estas tarefas. Código do usuário só pode ter acesso
a esta área via system calls.
•O código do usuário é bloqueado por US (user-supervisor) bit.
US=1 não bloqueia o acesso. Se US=0, dois bits de pivilégio
(do registrador CPL) são analisados. Código do usuário tem CPL=3.
•No Linux: CPL = 0 – tarefas do kernel
• CPL = 3 – tarefas do usuário.
Programação de Baixo Nível em
Linux

• Paginação
• Entradas das Page (Table) Table

31 12 11 2 1 0
U W P
Endereço da página
S R P

•Memória onde é próibido a escrita WR =0


•Memória onde é possível a escrita WR =1
Introdução ao NASM e a
programação em ambiente Linux
• Segmento de código e dados:
• Código
[SECTION] .text
• Dados
[SECTION] .data •Defines
• Exemplo: x db 2 byte
global main y dw 3 2 bytes
[SECTION .text]
main : push ebp z dq 4 4 bytes
mov ebp,esp z1 dt 5 10 bytes
push ebx; Program a dever preservar ebp, ebx, esi, edi
push esi
push edi
MOV AL,[XYZ]
INC AL
MOV [XYZ],AL
pop edi ; Restaura registradores
pop esi [SECTION] .data]
pop ebx XYZ: db 3
mov esp,ebp
pop ebp
RET
Introdução ao NASM e a
programação em ambiente Linux
• Dados não inicializados

[SECTION .bss] Sintaxe:


X resb 1 res(b/w/d/q/t) #de ítens
Y resb 128
Z resq 4

Reserva
x resb 1 byte
y resw 1 2 bytes
z resd 1 4 bytes
z1 resq 1 8 bytes
z2 rest 1 10 bytes
Introdução ao NASM e a
programação em ambiente Linux
• Dados não inicializados
[SECTION .text] ret
global main ABC db “Entre um número”,0AH,0
main : BCD db “%d \x0”, 0AH,0
CDE db “Voce obteve %d. \x0”,0AH,0
push epb
mov ebp,esp [SECTION .data]
push ebx XYZ db 4 * 0
push esi
push edi [SECTION .bss]
X resb 1
; sua funcionalidade Y resb 128
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
Introdução ao NASM e a
programação em ambiente Linux

• Vimos que os programas têm segmentos que devem ser


salvos em página diferentes devido aos requisitos de
escrita (áreas que podem ser escritas ou não).
• Portanto, estas localizações devem ficar explícitas no
arquivo executável para que o SO possa carregar estas
áreas em páginas de memória física que respeitem estas
restrições.
• Por estas razões, os arquivos executáveis devem ter um
formato definido.
• Desde a versão 2.0 do Linux o formato adotado tem sido o
ELF.
Introdução ao NASM e a
programação em ambiente Linux

• Arquivos Executáveis em ELF


• ELF – Executable and Linking Format
• SO Unix consideram três formatos para
arquivos executáveis: COFF (Commom Object
File Format), a.out (não há relação com o
arquivo gerado pelo compilador C) e ELF.
• Nas versões atuais dos SO Unix ELF é o
formato mais comum.
Introdução ao NASM e a
programação em ambiente Linux

• Formato ELF
ELF Header
Segment 1
Segment 2
Segment 3
Segment 4
Program Header Table
Section Header Table
Section 1

Section n
Introdução ao NASM e a
programação em ambiente Linux

• Formato ELF

o Arquivos executáveis do Linux 2.0 tem normalmente pelo menos 5


segmentos (lembrem que estamos falando de áreas e não de
segmentação de memória):
o o Segmento 0 é o Program Header.
o Os outros são:
o Um para código e informações que não possam/precisem ser alteradas
em tempo de execução,
o Um para dados inicializados e que precisam ser alterados ao longo da
execução do programa,
o Um para dados não inicializados e
o Um para dados cujo espaço de memória será alocado dinamicamente.
Introdução ao NASM e a
programação em ambiente Linux

• ELF Header
o Identifica o arquivo como um arquivo ELF e especifica o seu tipo.
Também define o tamanho e localização do Program Header
Table e da Section Header Table.
o O formato do ELF Header é:
o Primeiro entrada: string de identificação contendo ELF.
o Segunda entrada: número que especifica o tipo do arquivo:
1 – arquivo objeto
2 – arquivo executável
3 – arquivo objecto compartilhado
4 – arquivo core
o Terceira entrada: especifica a arquitetura – 3 = arquitetura x86.
o Tem-se 11 entradas a mais.
Introdução ao NASM e a
programação em ambiente Linux

• Program Header Table


o O Program Header Table tem uma entrada para cada segmento.
Cada entrada contém oito ítens de informação.
o Type: 1 se o segmento deve ser carregado quando o arquivo é
executado. Os outros tipos não são carregados .
o File Offset: fornece a localização do segmento dentro do arquivo –
número de bytes a partir do início do arquivo.
o Virtual Address: o endereço onde deve ser armazenado o primeiro
byte do segmento.
o Phisical Address: não é considereado na arquitetura x86.
o File Size: número de bytes no segmento antes de ser carregado.
o Memory Size: número de bytes no segmento depois da carga.
o Permissions: este código contém informações relacionadas a
permissões de leitura, escrita e execução.
o Aligment: o segmento deve começar em um múltiplo deste número.
Introdução ao NASM e a
programação em ambiente Linux

• Program Header Table


o Permissions
r w x
1 1 0 = 6 leitura e escrita
1 0 1 = 5 leitura e execução

1 = habilita opção
0 = desabilita opção

O programa ob fornece o Program Header Table de um


arquivo
Introdução ao NASM e a
programação em ambiente Linux

• Section Header Table


• Fornece informações sobre todas as seções do arquivo. As
informações são atibutos sobre permissão (leitura, escrita e
execução), tipo (programa, tabela de símbolos, informação
dinâmica etc)
• Seções
• Quando o linker cria segmento de texto/dados (código/dados),
combina seções de texto/dados (código/dados) dos arquivos
objeto.
• Quando linker liga os arquivos objeto é necessário definir o
endereço onde a execução deve ser iniciada. O programador
pode faze-lo utilizando o label main e tornando-o visível para
todas as seções (linker) através da diretiva global.
Introdução ao NASM e a
programação em ambiente Linux
• Ponto de Entrada
[SECTION .text] ret
global main ABC db “Entre um número”,0AH,0
main : BCD db “%d \x0”, 0AH,0
CDE db “Voce obteve %d. \x0”,0AH,0
push epb
mov ebp,esp [SECTION .data]
push ebx XYZ db 4 * 0
push esi
push edi [SECTION .bss]
X resb 1
; sua funcionalidade Y resb 128
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
Introdução ao NASM e a
programação em ambiente Linux
• Como o gcc constrói arquivos executáveis Linux
gcc exe1.c –o exe1
.c

cpp
.c

gcc
.s
gas
.o
ld
executável
Introdução ao NASM e a
programação em ambiente Linux
• Como usar o gcc em trabalhos com assembly
• Evitamos o gas, devido a sintaxe dos mnemonicos
AT&T.
• Usaremos Nasm (assembler) + ferramentas gcc como
linker.

• nasm –f elf exe1.asm - assembler


• gcc exe1.o –o exe1 - linker
Introdução ao NASM e a
programação em ambiente Linux
• Outra informação:
• gcc –S nome.c
• O comando acima gera um arquivo nome.s que é um assembly
no formato AT&T (você pode investigar este arquivo para
compreender como o C “funciona”)

• Exemplo1:
no Vmware em /mnt/hgfs/C/teste_pont , verifique os arquivos
t1.c e t1.s
• Exemplo1:
no Vmware em /mnt/hgfs/C/teste_pont , verifique os arquivos
t2.c e t2.s
Introdução à Integração C e Assembly
em ambiente Linux

• Passagem de Parâmetros em Funções C


sum(a,b,c,d)

Padrão C
Introdução à Integração C e Assembly
em ambiente Linux

• Passagem de Parâmetros em Funções C


Introdução à Integração C e Assembly
em ambiente Linux

• Passagem de Parâmetros em Funções C

• Em geral os registradores EBP, EBX, ESI e EDI


são preservados (ou seja, não são usados nas
funções), mas isto não é uma regra.
Introdução à Integração C e Assembly
em ambiente Linux

• Retorno de Valores de Funções C


• Valores de 8, 16 e 32 bits são devolvidos em EAX,

• Valores de 64 bits são devolvidos em EDX:EAX,

• Valores de ponto flutuante são devolvidos em ST0,

• Endereços (ponteiros) são devolvidos em EAX.


Introdução à Integração C e Assembly
em ambiente Linux
#include <stdio.h> push ebx ; Program must preserve ebp, ebx, esi, &edi
push esi
extern int increm(int z); Não considere o push edi
int main(void) código em vermelho
{ push dword msg; Push a 32-bit pointer to the message on
the stack
int x,y;
call puts ; Call the C library function for displaying strings
x=1; add esp, 4 ; Clean stack by adjusting esp back 4 bytes
y=increm(x);
printf("x 'e %d e y e‘ %d\n",x,y); pop edi ; Restore saved registers
pop esi
(0); pop ebx
}
pop eax ; recovering eax
[SECTION .text] ; Section containing code
mov esp,ebp ; Destroy stack frame before returning
pop ebp
extern puts ; Simple "put string" routine from C library ret ; Return control to Linux
global increm ;Required so linker can find entry point
[SECTION .data] ; Section containing initialised data
increm:
push ebp ; Set up stack frame for debugger msg: db "Teste!",0
mov ebp,esp
mov eax,[ebp+8] [SECTION .bss] ; Section containing uninitialized data
inc eax ; incrementing the parameter value
push eax ; pushing the result, since puts might use eax
Introdução à Integração C e Assembly
em ambiente Linux

• Veja exemplo em:


/mnt/hgfs/C/teste
(teste.c e increm.asm)
no VMWare Mandrake Linux
Veja o arquivo CompilarExecutar:
>mnt/hgfs/Nasm/nasm-0.98/nasm -f elf /mnt/hgfs/C/teste/increm.asm
>gcc -c teste.c -o teste.o
>gcc teste.o increm.o -o teste
>/mnt/hgfs/C/teste/teste
- c informa ao gcc para para após a compilação (não linkar).
Introdução à Integração C e Assembly
em ambiente Linux

• Veja exemplo em:


/mnt/hgfs/C/teste
(teste.c e increm.asm)
no VMWare Mandrake Linux
Veja o arquivos makefile:
teste: teste.o increm.o
gcc teste.o increm.o -o teste
teste.o: teste.c
gcc -c teste.c -o teste.o
increm.o: increm.asm
/mnt/hgfs/Nasm/nasm-0.98/nasm -f elf /mnt/hgfs/C/teste/increm.asm

- c informa ao gcc para para após a compilação (não linkar).


Introdução à Integração C e Assembly
em ambiente Linux

• Passagem de Parâmetros em Funções C

• Instrução enter

• enter bytes,level
• bytes – número de bytes relativos as variáveis locais
da função (procedimento).
• level – nível de aninhamento do procedimento.
Introdução à Integração C e Assembly
em ambiente Linux

• Passagem de Parâmetros em Funções C

• Instrução enter

Exemplo:
enter xx,0
Introdução à Integração C e Assembly
em ambiente Linux

• Passagem de Parâmetros em Funções C

• Instrução leave

Exemplo:
leave
Introdução à Integração C e Assembly
em ambiente Linux

Introdução à Integração C e Assembly
em ambiente Linux
• Assembly chama bibliotecas C – Escrita em Tela
; nasm –f elf exe1.asm
pop edi
;gcc exe1.o –o exe1 pop esi
[SECTION .text] pop ebx
extern puts mov esp,ebp
global main pop ebp
ret
main :
[SECTION .data]
push ebp mens1 db “Bom Teste”,0AH,0
mov ebp,esp
push ebx
push esi [SECTION .bss]
push edi
push dword mens1
call puts
add esp,4
Introdução à Integração C e Assembly
em ambiente Linux

• Assembly chama bibliotecas C – mov eax,[XYZ]


add eax,eax
Escrita Formatada em Tela inc eax
[SECTION .text] push eax
global main push dword CDE
extern printf call printf
main : add esp,8
push epb pop edi
mov ebp,esp pop esi
pop ebx
push ebx
mov esp,ebp
push esi
push edi pop ebp
ret
push dword ABC ABC db “Bom Dia”,0AH,0
CDE db “O valor e’ %d. \x0”,0AH,0
call printf
add esp,4
[SECTION .data]
XYZ db 4
Introdução ao NASM e a
programação em ambiente Linux

• Inserindo Sub-rotina em Bibliotecas


• Crie um arquivo com código fonte e insira a sub-rotina neste
arquivo. O arquivo deve ter a extensão .asm. Este arquivo não
deve ter ponto de entrada (main).
• Associe o termo global a todos os lables associados as rotinas
que serão chamadas e todos os demais lables que venha ser
utilizados por programas chamadores.
• Caso as sub-rotinas chamem rotinas em bibliotecas C ou
outras rotinas em outras bibliotecas que você mesmo tenha
criado, ou ainda usem variáveis ou identificadores definidos
fora da rotina, declare tais identificadores como extern.
Introdução ao NASM e a
programação em ambiente Linux

• Inserindo Sub-rotina em Bibliotecas


• Utlitário make realiza um conjunto de atividade
descritas no makefile, contudo executando apenas o
que foi alterado (verificado pela data de alteração dos
arquivos) desde a última execução.
Introdução à Integração C e Assembly
em ambiente Linux

• Inserindo Sub-rotina em Bibliotecas


• Quando adicionar rotinas de uma biblioteca ao seu programa,
atualize o makefile deste programa de maneira que o
executável tenha as dependências das bibliotecas.
• Exemplo de makefile:
textfile: textfile.o linlib.o - dependência
gcc textfile.o linlib.o –o textfile - como obter textfile
textfile.o: testfile.asm -dependência
nasm –f elf textfile.asm - como obter textfile.o
linlib.o: linlib.asm - dependência
nasm –f elf linlib.asm - como obter linlib.o
Introdução à Integração C e Assembly
em ambiente Linux

• Veja exemplo em:


/mnt/hgfs/C/eagtlinux
(eagtlinux.asm)
no VMWare Mandrake Linux

Veja os arquivos makefile, o fonte ( .asm) e os arquivos


CompilarExecutar
Introdução à Integração C e Assembly
em ambiente Linux

; Build using these commands: add esp, 4 ; Clean stack by adjusting esp back 4
; nasm -f elf eatlinux.asm bytes
; gcc eatlinux.o -o eatlinux
;
pop edi ; Restore saved registers
pop esi
[SECTION .text] ; Section containing code
pop ebx
extern puts ; Simple "put string" routine from C mov esp,ebp ; Destroy stack frame before returning
library pop ebp
global main ; Required so linker can find entry point
ret ; Return control to Linux
main:
push ebp ; Set up stack frame for debugger
mov ebp,esp [SECTION .data] ; Section containing
push ebx ; Program must preserve ebp, ebx, esi, & edi initialised data
push esi
push edi eatmsg: db "Eat at Joe's!",0

push dword eatmsg ; Push a 32-bit pointer to the message on the stack
[SECTION .bss] ; Section containing
call puts ; Call the C library function for displaying strings
uninitialized data
Introdução à Integração C e Assembly
em ambiente Linux

• Veja exemplo em:


/mnt/hgfs/C/eagtlinux
(eagtlinux.asm)
no VMWare Mandrake Linux

Veja o arquivo CompilarExecutar

>/mnt/hgfs/Nasm/nasm-0.98/nasm -f elf /mnt/hgfs/C/eatlinux/eatlinux.asm


>gcc eatlinux.o -o eatlinux
>/mnt/hgfs/C/eatlinux/eatlinux
Introdução à Integração C e Assembly
em ambiente Linux

• Veja exemplo em:


/mnt/hgfs/C/eagtlinux
(eagtlinux.asm)
no VMWare Mandrake Linux

Veja o arquivo makefile:


eatlinux: eatlinux.o
gcc eatlinux.o -o eatlinux
eatlinux.o: eatlinux.asm
/mnt/hgfs/Nasm/nasm-0.98/nasm -f elf /mnt/hgfs/C/eatlinux/eatlinux.asm
Introdução à Integração C e Assembly
em ambiente Linux

• Inserindo Sub-rotina em Bibliotecas


• Quando chamar rotinas assembly contidas em um arquivo de
um programa C (em outro arquivo), atualize o makefile de
maneira que o executável tenha as dependências das
bibliotecas.
• Exemplo de makefile:
textfile: textfile.o linlib.o - dependência
gcc textfile.o linlib.o –o textfile - como obter textfile
textfile.o: testfile.c -dependência
gcc –c textfile.c –o textfile.o - como obter textfile.o
linlib.o: linlib.asm - dependência
nasm –f elf linlib.asm - como obter linlib.o
- c informa ao gcc para para após a compilação (não linkar).
Introdução à Integração C e Assembly
em ambiente Linux

• Veja exemplo em:


/mnt/hgfs/C/teste
(teste.c e increm.asm)
no VMWare Mandrake Linux

Veja os arquivos makefile os fontes (.c e .asm) e os


arquivos CompilarExecutar
Introdução à Integração C e Assembly
em ambiente Linux

• Assembly chama bibliotecas C – Leitura do Teclado


com fgets

• Manipuladores de Arquivo Padrão:


• stdin (teclado)
• stdout (tela)
• stderr (tela)
• Para utilizar um manipulador no seu código assembly,
declare-o com externo.
Introdução à Integração C e Assembly
em ambiente Linux

• Assembly chama bibliotecas C – Leitura do Teclado


com fgets
• Como usar o fgets
• Declare: extern fgets e extern stdin
• Declare um buffer (use a diretiva resb) em uma seção [.bss] de
tamanho suficiente para armazenar o dado.
• Empilhe o manipulador, o valor que representa o número máximo
de carateres a serem lidos e o endereço do buffer onde queremos
armazenar as informações.
Introdução à Integração C e Assembly
em ambiente Linux

• Assembly chama bibliotecas C –


Leitura do Teclado com fgets
[SECTION .text]
global main [SECTION .data]
extern stdin
extern fgets
main : [SECTION .bss]
push ebp instring resb 96
mov ebp,esp
push ebx
push esi
push edi
push dword [stdin]
push dword 72
push instring
call fgets
add esp,12
ret
Introdução à Integração C e Assembly em
ambiente Linux
Leitura do Teclado com scanf

add esp,8
[SECTION .text] mov eax,[XYZ]
global main add eax,eax
extern printf inc eax
extern scanf push eax
main : push dword CDE
push epb call printf
mov ebp,esp add esp,8
pop edi
push ebx
pop esi
push esi
pop ebx
push edi mov esp,ebp
pop ebp
push dword ABC
ret
call printf
ABC db “Entre um número”,0AH,0
add esp,4
BCD db “%d \x0”, 0AH,0
push dword XYZ CDE db “Voce obteve %d. \x0”,0AH,0
push dword BCD
call scanf [SECTION .data]
XYZ db 4 * 0
Introdução à Integração C e Assembly
em ambiente Linux
add esp,8
• Chamando C do Assembler mov eax,[XYZ]
[SECTION .text] add eax,eax
global main inc eax
extern printf push eax
extern scanf push dword CDE
main : call printf
push epb add esp,8
mov ebp,esp pop edi
push ebx pop esi
push esi pop ebx
push edi mov esp,ebp
pop ebp
push dword ABC ret
call printf ABC db “Entre um número”,0AH,0
add esp,4 BCD db “%d \x0”, 0AH,0
push dword XYZ CDE db “Voce obteve %d. \x0”,0AH,0
push dword BCD
call scanf [SECTION .data]
XYZ db 4 * 0
Introdução à Integração C e Assembly
em ambiente Linux

• Usando Funções de Tempo do C


• Está estabelecido que a “Era” Unix iniciou-
se em 1 de Janeiro de 1970 as 00:00:00 hs
• A cada segundo que se passa adiciona-se 1 a
este valor.
• Quando você ler o tempo ou uma data
através de bibliotecas do C, você obtêm o
número atual desta associado a uma variável.
• Esta variável é denominada time_t.
• Para obter o valor de time_t, chama-se a
função time.
Introdução à Integração C e Assembly
em ambiente Linux

• Usando Funções de Tempo do C


• A função time pode retornar valores de duas
maneiras:
• em EAX
• em um buffer que você tenha definido
• Para ter o tempo armazenado no buffer você
tem que passar o ponteiro do endereço inicial
do buffer como parâmentro (via pilha).
• Se você não quer armazenar o tempo no
buffer, você tem que passar um ponteiro nulo
(0) como parâmetro.
Introdução à Integração C e Assembly
em ambiente Linux

• Usando Funções de Tempo do C


[SECTION .text]
global main pop edi
extern time pop esi
pop ebx
main :
mov esp,ebp
push epb
mov ebp,esp pop ebp
push ebx ret
push esi [SECTION .data]
push edi …
[SECTION .bss]
push dword 0 oldtime resb 4
call time
add esp,4
mov [oldtime],eax
Introdução à Integração C e Assembly
em ambiente Linux

• Usando Funções de Tempo do C


• Existe uma função que converte o valor
obtido por time em uma string formatada
como o exemplo: Thu Dec 2 13:59:20 1999
• Esta função é ctime.
• Para usa-la você deve passar o endereço da
variável que tem a informação do tempo.
Introdução à Integração C e Assembly
em ambiente Linux

• Usando Funções de Tempo do C


[SECTION .text]
global main push dword oldtime ;empilha-se o endereço
extern time ; de oldtime
extern ctime call ctime ; retorna um ponteiro
main : ; para a string em EAX
add esp,4
push epb

mov ebp,esp
pop edi
push ebx pop esi
push esi pop ebx
push edi mov esp,ebp
pop ebp
push dword 0
ret
call time [SECTION .data]
add esp,4 …
mov [oldtime],eax [SECTION .bss]
oldtime resb 4
Introdução à Integração C e Assembly
em ambiente Linux

• Usando Funções de Tempo do C


• Há uma estrutura que agrupa nove informações de 32 bits
relacionadas com o tempo: a estrutura tm.
• Valores contidos na estrutura tm:
• offset em bytes C library name Definição
0 tm_sec segundos
4 tm_min minutos
8 tm_hour horas
12 tm_mday dia do mês
16 tm_mon mês
20 tm_year ano
24 tm_wday dia da semana
28 tm_yday dia do ano
32 tm_isdst flag para daylight savings
Introdução à Integração C e Assembly
em ambiente Linux

• Usando Funções de Tempo do C


• Há uma estrutura que agrupa nove informações de 32
bits relacionadas com o tempo: a estrutura tm.
• Para obter as informações de tempo através da
estrutura tm, chama-se a função localtime.
• Passa-se time_t como parâmetro (via pilha).
• localtime retorna um ponteiro em EAX que aponta
para o endereço base da estrutura tm.
Introdução à Integração C e Assembly
em ambiente Linux
push dword oldtime
• Usando Funções de Tempo do C call localtime
[SECTION .text] add esp,4
global main mov edx, dword[eax+20]
extern time push edx
push dword yrmsg
extern localtime
call printf
extern printf
add esp,8
main :

push epb pop edi
mov ebp,esp pop esi
push ebx pop ebx
push esi mov esp,ebp
push edi pop ebp
ret
push dword 0 [SECTION .data]
call time yrmsg db “O ano e’19%d.”,10,0
add esp,4 [SECTION .bss]
mov [oldtime],eax oldtime resb 4
Introdução à Integração C e Assembly
em ambiente Linux

Ponto Flutuante
Endereçamento de Memória

• Segmentação no Modo Protegido:


Endereço Lógico

Seletor de 16 bits Offset de 32 bits MOV EAX,[DS:00080000H]


GDT/LDT = registradores
0H
0
8H
1
10H
2 Segment Descriptor
18H Σ Endereço Linear – 32 bits
3
32 bit
base address Paging
Translation
FFF8H
Global/Local 8191 Endereço Físico – 32 bits
Descriptor Table
Endereçamento de Memória

• Segmentação no Modo Protegido


• Registradores Seletores:
• CS,DS,ES,FS,GS,SS

• Layout do Seletor:

Índice – 13 bits TI RPL


Indicador de Tabela
0 – GDT 00 – mais alto
01
1 - LDT Privilégio
10
11 – mais baixo
Endereçamento de Memória

• Segmentação no Modo Protegido


• Layout do Seletor:
Índice – 13 bits TI RPL
Indicador de Tabela
0 – GDT 00 – mais alto
01
1 - LDT Privilégio
10
11 – mais baixo
• Ex.:
MOV AX,33H
MOV DS,AX Como cada segment descriptor
MOV EAX,[DS:00080000H] tem 8 bytes, o 3 bits LSB dos
seletores são desprezados.
Endereçamento de Memória

• Segmentação no Modo Protegido


• Layout do Seletor:
Índice – 13 bits TI RPL
Indicador de Tabela
0 – GDT 00 – mais alto
01
1 - LDT Privilégio
10
11 – mais baixo
• Ex.:
MOV AX,33H
MOV DS,AX 0 0 3 3 H
MOV EAX,[DS:00080000H]
0000 0000 0011 0011 b
0000 0000 0011 0000 = 0030 H
Endereçamento de Memória

• Segmentação no Modo Protegido:


Endereço Lógico

Seletor de 16 bits Offset de 32 bits MOV EAX,[DS:00080000H]


GDT/LDT = registradores
0H
0
8H
1
10H
2 Segment Descriptor
18H Σ Endereço Linear – 32 bits
3
32 bit
base address Paging
Translation
FFF8H
Global/Local 8191 Endereço Físico – 32 bits
Descriptor Table
Endereçamento de Memória

• Segmentação no Modo Protegido:


15 0

Segment limit Palavra 0

Segment Descriptor Base Address Palavra 1


Outras Base Address
P DPL Palavra 2
Inform. (16-23)
Base Address Outras
Palavra 3
(24-31) Inform.

P – segmento presente em memória


DPL – nível de privilégio
Endereçamento de Memória

• Segmentação no Modo Protegido:


Endereço
0000000H 64Mb RAM

Base: 2000000H
Limite: 00FFFFFH 2000000H
Σ 2080000H Segmento de 1MB
20FFFFFH
...
2080003H
MOV EAX,[DS:80000H]
3FFFFFFH

80003H < FFFFFH OK


Endereçamento de Memória

• Segmentação no Modo Protegido:


Endereço
0000000H 64Mb RAM

Base: 2000000H
Limite: 00FFFFFH 2000000H
Σ 2180000H Segmento de 1MB
20FFFFFH
...
2180003H
MOV EAX,[DS:180000H]
3FFFFFFH

180003H > FFFFFH General Protection Fault


Endereçamento de Memória

• Segmentação no Modo Protegido:


• No LINUX atual a base é 0H e o limite é
FFFFFFFFH, ou seja 4GB.
• Na prática: temos um único segmento.

Base: 00000000H
Limite: FFFFFFFFH
Endereçamento de Memória

• Segmentação no Modo Protegido:

Base: 00000000H
Limite: FFFFFFFFH

Σ 00180000H
...
00180003H
MOV EAX,[DS:180000H]

180003H < FFFFFFFFH OK


Endereçamento de Memória

• Segmentação no Modo Protegido:


Endereço Lógico

Seletor de 16 bits Offset de 32 bits MOV EAX,[DS: 801C3400H]


GDT/LDT = registradores
0H
0
8H
1 Endereço Virtual= 801C3400H
10H
2 Segment Descriptor
18H Σ Endereço Linear – 32 bits
3
32 bit
base address Paging
=00000000H
Translation
FFF8H
Global/Local 8191 Endereço Físico – 32 bits
Descriptor Table
Endereçamento de Memória

• Paginação
• Exemplo: enderço virtual 801C3400H

1000000000 0111000011 010000000000 Endereço Virtual

400H
200H
1C3H

01234+”000”
Endereço Físico
E4000+”000” + 01234400H

CR3
Page Table Table (Page Directory) Page Table
Endereçamento de Interrupções

• Interrupções no Modo Protegido


• No Petium o reconhecimento de uma interrupção é
sinalizada por D/C# = 0, M/IO# = 0 e W/R# = 0.
• Após o reconhecimento o Contolador coloca na parte
menos significativa do barramento de dados um
número de 8 BITS.
• O processador utiliza este número como um índice
para uma tabela denominada Interrupt Descriptor
Table (ITD). Esta tabela contém os endereços para os
serviços de interrupção.
Endereçamento de Interrupções

• Interrupções no Modo Protegido


• Dado que o número de uma interrupção é uma
informação de 8 bits, os números válidos de uma
interupção variam de 0 a 255.
• A criação e carga desta tabela é responsbilidade do
SO. Esta tarefa é executa na inicialização do sistema
(boot time)
• Processadores da arquitetura x86 têm um registrador
específico que armazena o endereço da ITD, o
registrador IDT.
Endereçamento de Interrupções

• Interrupções no Modo Protegido


• Existem instruções especiais para manipular o
registrador IDT:
• LIDT mem
Carrega o registrador com um enderço.
Esta instrução é utilizada na inicialização do sistema,
após a IDT ter sido criada, de maneira que o
registrador IDT terá o endereço base da tabela IDT.
• SIDT mem
Armazena o valor do registrador na memória.
Endereçamento de Interrupções

• Interrupções no Modo Protegido


Endereço
b gate # 0 Registrador IDT tem valor igual a b
b+8 gate # 1
b+16 gate # 2
b+24 gate # 3
.
.
.
b+2040 gate # 255
Endereçamento de Interrupções

• Interrupções no Modo Protegido


• Uma vez obtido o endereço da rotina de serviço de
interrupção (ISR), o processador empilha o endereço
da próxima instrução e o registrador EFLAGS.
• Quando o ISR é finalizada, o que é feito através do
IRET, o registrador EFLAGS são desempilhados,
assim como o endereço de retorno.
• As solicitações de interrupção só serão aceitas se IF
=1. As instruções STI e CLI habilitam e desabilitam
as interrupções, respectivamente.
Interrupções

• Interrupções no Modo Protegido


• No final da execução do serviço de interrupção, no PC – que
usa um PIC 8259 -, o programador envia um comando de fim
de interrupção (EOI) para o PIC. Este comando é executado
escrevendo-se no endereço 20h um valor informando a
finalização da interrupção de número especificado. Podemos
efetuar uma finalização genérica (sem determinar uma
interrupção específica). Fazemos isto enviando o valor 20h
(ver datasheet do PIC 8259).
• Ex.: mov dx,20h ; um endereço de controle da 8259 mestre no PC
out dx,20h ; EOI genérica
mov dx,0A0h ;um endereço de controle do 8259 escravo.
out dx,20h ; EOI genérica
Interrupções

• Interrupções no Modo Protegido


• NMI (non maskable interrupt) é a interrupção de
número 2.
• É não mascarável (não considera o IF).
• No PC é utilizada para tratar erros de paridade.
• O RESET pode ser considerado uma interrupção.
• Quando ocorre, executa-se o código do endereço
FFFFFFF0h, endereço contido na BIOS.
Interrupções

• Interrupções no Modo Protegido

IRQ0
IRQ1 IRQ8
IRQ3 IRQ9
8259 IRQ10
Mestre
IRQ4 8259 IRQ11
IRQ5 IRQ12
IRQ6
Escravo IRQ13
IRQ14
IRQ7 IRQ15

Circuito Controlador de Interrupção ISA


Interrupções

• Interrupções no Modo Protegido

• Interrupções de Software
• INT imm
imm é um valor de 8 bits que é usado para obter o
enderço da ISR correspondente.
Interrupções

• Interrupções no Modo Protegido


• Interrupções de Hardware Internas (Exceptions)
• Quando uma interrupção de hardware ou de software é finalizada, a
próxima instrução a ser executada é aquela instrução subseqüente a
insturção interrompida. Com as Exceptions nem sempre é assim.
• Quando se encerra a execução da maioria das Exeptions, a instrução
interrompida é novamente executada. Estas Exceptions são
denominadas de faults.
• Faults: quando uma instrução de movimentação tenta ler uma
informação qua não se encontra na memória principal (se encontra no
disco), ocorre uma fault. Após a execução da ISR correspondente, a
instrução de movimentação é novamente executada.
• Poucas Exceptions se comportam com intrrupções ordinárias, ou seja
passam o controle para a próxima instrução. Estas são chamadas de
traps.
• Traps: um exemplo típico é a Exception overflow.
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls
• Uma das funções básicas de SO é prover acesso a
dispositivos de hardware.
• No UNIX todo acesso a dispositivos de hardware é feito
via chamada a system calls.
• Normalmente, os usuários têm acesso a estes dispositivos
através de comandos UNIX tais quais ls, cp etc ou via
funções C – printf, scanf etc. Contudo, tanto os comandos
UNIX, assim como as funções C utilizam system calls
para se ter acesso ao hardware.
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls

Funções C
System
SO Hardware
Calls
Comandos
UNIX
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls
os comandos read() e write() são exemplos de system calls,
embora pareçam ser funções ordinárias do C.
• Exemplo:
void main(void) {
char s[] = “Hello World! \n”;

write(1,s,13);
}
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls
void main(void) {
char s[] = “Hello World! \n”;

write(1,s,13);
}
• Como todas as system calls em LINUX, write() usa INT 80h
para transferir o controle para o kernel.
• Toda system call no LINUX tem um número
• A lista destas chamadas e os respectivos números podem ser
encontradas em /usr/include/bits/syscall.h syscall unistd
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls
void main(void) {
char s[] = “Hello World! \n”;

write(1,s,13);
}
• No LINUX 2.0 a system calls write() tem número 4.
• Para executar esta system call em assembly o valor 4
deve ser armazenado em EAX antes de chamar INT
80h.
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls
void main(void) {
char s[] = “Hello World! \n”;

write(1,s,13);
}
• Para usar as system calls em assembly, é necessário conhecer o padrão
para passagem de parâmetros. Este padrão está estabelecido em macros
localizadas em /usr/include/bits/syscall.h
• De acordo com a norma utilizada no LINUX 2.2, os parâmentros são
armazenados, da esquerda para a direita, nos registradores
EBX,ECX,EDX,ESI e EDI.
• Em caso de mais argumentos, um ponteiro em EBX é passado para uma
estrutura com os argumentos.
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux
Ver exemplos em SysCall:
• Interrupções no Modo Protegido
write.c
• System Calls
outro1.asm,
void main(void) {
outro2.asm,
char s[] = “Hello World! \n”;
outro3.asm e
ponteiro.asm
write(1,s,13);
} systemcall\asmtut\quickstart.html
global main systemcall\asmtut\syscalls.html
main: …
mov eax,4 Uma lista das macro de chamadas
mov ebx,1 das funções pode ser encontrada no
mov ecx, dword ABC arquivo /usr/include/bits/syscall.h
mov edx,13 (pode ser alterado dependendo
int 80h da versão e distribuição).
ret
ABC db “Hello World!”,0Ah,0
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux
[section .data] mov eax,1
hello db 'Hello, world!',10
int 80h
helloLen equ $ - hello
[section .text] ; proc fileWrite - write a string to a file
global _start fileWrite:
_start: mov ebx,eax
pop ebx mov eax,4
pop ebx mov ecx,hello
pop ebx mov edx,helloLen
mov eax,8
int 80h
mov ecx,00644Q
mov eax,6
int 80h
int 80h
test eax,eax
js skipWrite ret
call fileWrite ; endp fileWrite
skipWrite: mov ebx,eax
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

 Acesso ao I/O
 int ioperm(unsigned long from,unsigned long num, int turn_on);

 unsigned long from : endereço inicial dos endereços das portas


 unsigned long num : deslocamento
 int turn_on : 1 = habilita e 0 = desabilita

 Faixa de Endereço das portas: até 3FFh


Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

 Acesso ao I/O
C:
ioperm(0x378,4,1); // ativa permissão
ioperm(0x378,4,0); // desativa permissão
Assembly:
mov eax,101 mov eax,101
mov ebx,0x378 mov ebx,0x378
mov ecx,4 mov ecx,4
mov edx,1 mov edx,0
int 0x80 int 0x80
Ativa permissão Desativa permissão
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

 Acesso ao I/O
C:
ioperm(0x378,4,1); // ativa permissão
outb(0x10,0x378);
ioperm(0x378,4,0); // desativa permissão
Assembly:
mov eax,101 mov eax,101
mov ebx,0x378 mov ebx,0x378
mov ecx,4 mov ecx,4
mov edx,1 mov edx,0
int 0x80 int 0x80
mov al,0x10
out 0x378,al
Ativa permissão e escreve Desativa permissão
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

 Acesso ao I/O
 int ioctl(int level);

 int level = nível

 Endereço das portas: todas as portas (65 535


endereços)
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls
• Quando uma system call é executada pelo processador é
porquê o programa necessita utilizar o kernel para realizar
alguma tarefa que não está habilitado a faze-lo. Por
exemplo, ler um arquivo, escrever no monitor etc.
• O programa é incapaz de realizar estas tarefas, pois o
processador está bloqueado para realiza-las enquanto
estiver executando código de usuário.
• A diferença entre código de usuário e código do kernel é a
diferença de nível de privilégio.
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls - Privilégios
• Desde o 286 o sistema de proteção é baseado em 4 níveis
de privilégio:
• 0 – privilégio no nível de sitema – usado pelo kernel
do LINUX
• 1 – não usado no LINUX
• 2 – não usado no LINUX
• 3 – privilégio de usuário- usado por programas de
usuário do LINUX.
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls - Privilégios
• O nível de privilégio do código em execução é
denominado current privilege level. Esta informação é
armazenada em um registrador de 2 bits denominado
registrado CPL.
• Alterar o valor do registrador CPL para 0 “destroi” a
proteção do sistema.
• Atibui-se 0 ao registrador CPL toda vez que uma system
call é executada.
Introdução à Integração C e Assembly e
chamadas às System Calls em ambiente Linux

• Interrupções no Modo Protegido


• System Calls - Privilégios
• O uso da instrução LIDT pode alterar o valor do
registrador IDT, alterando o acesso a tabela de
interrupções para uma outra tabela de interrupções (no
novo endereço do registrador IDT). Este é um exemplo de
uma instrução privilegiada. Instruções privilegiadas só
podem ser executadas se CPL=0.
• Caso se tente executar uma instrução privilegiada com
CPL>0, uma Exception é gerada (general protection
error).
Endereçamento de Interrupções

• Interrupções no Modo Protegido – Gate Layout


Endereço
b gate # 0 Registrador IDT tem valor igual a b
b+8 gate # 1
b+16 gate # 2 63 48 44 43 40 39 16 15 0
b+24 gate # 3 End. ISR 2
Tipo
End. ISR 2
Bytes MSB Bytes LSB
.
Gate Layout
.
.
b+2040 gate # 255
Endereçamento de Interrupções

• Interrupções no Modo Protegido


63 48 44 43 40 39 16 15 0
End. ISR 2 End. ISR 2
Bytes MSB
Tipo Bytes LSB
Gate Layout
• Valor de 4 bits que define o tipo (bits 40-43)
• Endereço da ISR é obtido nas duas faixas: bits 48-63 e 0-15, totalizando
32 bits de endereço.
• Interrupt gates são usadas para interrupções de hardware. Trap gates são
usadas para system calls (INT 80h).
• Os valores do campo tipo podem ser 14 = interrupt gate ou 15 = trap gate.
• Se o valor do campo tipo é 14 então IF = 0. Caso o valor do campo tipo
seja 15, o IF não é resetado.
Interrupções

• Interrupções no Modo Protegido

• O próximo passo no processamento de uma interrupção é


armazenar 0 no registrado CPL.
• O valor original do registrador CPL é restaurado quando o
IRET for executado.
• Antes de desviar para a ISR, o endereço de retorno é
emplilhado. O novo valor de EIP é carregado dos campos de
endereço do respectivo gate.
Linux Boot Time
Programming
• Uma Primeira Visão
• Modos de Operação dos Processadores da família
x86 atuais:

• Modo Real
• Modo Protegido
• Modo Virtual
• Modo de Gerenciamento
Linux Boot Time
Programming
• Uma Primeira Visão
• Modos de Operação dos Processadores da família
x86 atuais:

• Modo Real
• Modo Protegido
• Modo Virtual
• Modo de Gerenciamento
• Na inicialização, o processador está no Modo Real
Linux Boot Time
Programming
• Uma Primeira Visão
• Preparação para mudar para Modo Protegido:
• Preparar a Global Descriptor Table
• Armazenar código em local apropriado, pois quando
houver a mudança para o modo protegido os endereços
físicos serão gerados de maneira completamente diferente.
• Prepara a Interrupt Descriptor Table (IDT), pois os
vetores da IDT são de 8 bytes e os vetores da tabela de
vetores de interrupção do DOS são de apenas 4 bytes.
• Executar o código de mudança para o modo protegido.
Linux Boot Time
Programming
• Uma Primeira Visão
• Preparação para mudar para Modo Protegido:
• Preparar a Global Descriptor Table
• O Processador tem um registrador de base e um de limite
para a Global Descriptor Table. Estes registradores são
carregados com a instrução LGDT mem.
• mem é o endereço base de uma região de 6 bytes que
armazena: 2 bytes de limite + 4 bytes de endereço base
para Global Descriptor Table.
Linux Boot Time
Programming
• Uma Primeira Visão
• Preparação para mudar para Modo Protegido:
• Preparar a Global Descriptor Table
• Suponha que queiramos definir uma Global Descriptor
Table com 10 descritores e que o endereço base da GDT é
10000H.
• Como cada descritor tem 4 palavras (8 bytes), a GDT terá
80 bytes (50H). Portanto, o limite é 80-1= 79 (50H – 1H =
4FH).
Linux Boot Time
Programming
• Uma Primeira Visão
• Preparação para mudar para Modo Protegido:
• Preparar a Global Descriptor Table
• Desta forma, usaremos uma área de memória para
armazenar estas informações (limite e endereço base).
MOV AX,2000H
MOV DS,AX
MOV AX,4FH
MOV [DS:0],AX ;armazena o limite
MOV EAX,100000H
MOV [DS:2],EAX ; armazena o endereço base
LGDT [DS:0] ; carrega os rgistradores de base e de limite
Linux Boot Time
Programming
• Uma Primeira Visão
• Preparação para mudar para Modo Protegido:
• Executa código de mudança para o modo protegido.
• Os processadores da família x86 têm um registrador de
controle denominado CR0. Quando o bit 0 deste
registrador é feito 1, o processador muda para o Modo
Protegido.
MOV EAX,CR0
OR EAX,1
MOV CR0,EAX ; muda para o modo protegido
Linux Boot Time
Programming
• Uma Primeira Visão
• Preparação para mudar para Modo Protegido:
• Ao mudar para o Modo Protegido o processador não
inicia a paginação. Tornando o bit 31 do CR0 igual a 1,
faz com que se inicie o processo de paginação.
• 31 - PG = Paginação habilitada
• 30 - CD = Cache Desabilitada
• 29 - NW = No Writethrough
• 15 - WP = Write Protection
• 2 - EM = Emulate Math chip
• 1 - MP = Math chip Present
• 0 - PE = Protect Mode Enable

Anda mungkin juga menyukai