Laboratório de Organização e
Arquitetura de Computadores
Segmentação
(Conceitos Básicos)
PROFESSORES:
Elmar Uwe Kurt Melcher
Joseana Macêdo Fechine
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
#define VIDEOSEL 0x1000
/*** struct and type declarations ***/
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int dword;
/* endereco segmentado (endereco logico) */
struct segaddr {
void *addr;
word selector;
};
typedef struct segaddr *segaddr_ptr;
// tornar um seletor um indice da tabela de descritores de segmentos
#define segidx(selector) (selector>>3)
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
/* descritor de segmento. Cada sub-estrutura serve para preencher
uma parte dos campos do descritor. Devem ser usados na
sequencia a, b, c.*/
union segment { /* Nenhum dos itens na, nb deve ser usado. */
struct { // COLOCO BASE E LIMITE OS DEMAIS FICAM ERRADO
dword limit;
dword base;
} a;
struct {
word na;
dword base;
} b;
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
struct { //CONSERTA O TYPE E O BIT SIZE
dword na;
byte nb;
byte type;
byte bitsize;
} c;
};
typedef union segment *segment_ptr;
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
/* IDTR e GDTR */
struct dtr {
word length;
union {
gate_ptr
g;
segment_ptr s;
} base;
};
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
// Tem quase tudo que tem dentro do do processador
//FUNCAO: salvar o contexto do processador
struct tss {
/* itens na ate nk sao reservados */
word link,
na;
dword esp0; word ss0,
nb;
dword esp1; word ss1,
nc;
dword esp2; word ss2,
nd;
dword cr3;
//da paginacao
dword eip;
//PC
dword eflags;
//PSW
dword eax, ecx, edx, ebx;
dword esp, ebp;
dword esi, edi;
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
word es,
ne;
word cs,
nf;
word ss,
ng;
word ds,
nh;
word fs,
ni;
word gs,
nj;
word ldtr,
nk;
word t;
word iopb;
};
typedef struct tss *tss_ptr;
//Descritores
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
/*** declaracoes de variaveis globais ***/
/* interrupt table e global descriptor table */
struct dtr idtr, gdtr;
/* rotina especial para prencher o segmento de video */
void descVideo() {
dword *desc = (dword *)(gdtr.base.s + segidx(VIDEOSEL));
desc[1] = 0xE04BF200; // base = 0xE0000000,
limit=BFFFFh=1024*768-1<>1M
desc[0] = 0x0000FFFF; // tipo = 0xF2, dpl=3, read/write
}
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
/* carregar um arquivo executavel */
void carregar(char *exename) {
FILE *exefile;
// cabecalho do execut vel
static struct { dword datasize, codesize, varsize, stacksize; } header;
if((exefile=fopen(exename,"rb"))==NULL) {
fprintf(stderr,"Executavel %s ausente.\n", exename);
exit(1);
}
if(fread(&header, sizeof(header), 1, exefile)!=1) {
fprintf(stderr,"Nao consigo ler o cabecalho do executavel.\n");
exit(1);
}
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
//Preenchendo o descritor(seletor) de dados constantes
gdtr.base.s[segidx(0x1048)].a.limit = header.datasize-1; //o limite
esta no cabecalho -1 pois comeca em 0
gdtr.base.s[segidx(0x1048)].a.base = 0x01989866; //a base do
segmento a, um endereco gostoso
gdtr.base.s[segidx(0x1048)].b.base = 0x01989866; //a base do
segmento a, um endereco gostoso
gdtr.base.s[segidx(0x1048)].c.type = 0xF0; // dpl=usuario, permite so
leitura
gdtr.base.s[segidx(0x1048)].c.bitsize = 0x40;
// do descritor 32 bits
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
//Preenchendo o descritor(seletor) de codigo
gdtr.base.s[segidx(0x1050)].a.limit = header.codesize-1; //o codesize
est no cabecalho, -1 pois comeca em 0
gdtr.base.s[segidx(0x1050)].a.base = 0x01AA9866; //a base do
segmento a, o max ‚ FFFFFFF...
gdtr.base.s[segidx(0x1050)].b.base = 0x01AA9866; //a base do
segmento a, o max ‚ FFFFFFF...
gdtr.base.s[segidx(0x1050)].c.type = // 0x98; // dpl = S.O., permite
execucao
0xF8; // dpl=usuario, permite
execucao
gdtr.base.s[segidx(0x1050)].c.bitsize = 0x40;
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
//Preenchendo o descritor(seletor) de variaveis
gdtr.base.s[segidx(0x1058)].a.limit = header.varsize-1; //o limite
est no cabecalho, -1 pois comeca em 0
gdtr.base.s[segidx(0x1058)].a.base = 0x01BB9866; //a base do
segmento a, o max ‚ FFFFFFF...
gdtr.base.s[segidx(0x1058)].b.base = 0x01BB9866; //a base do
segmento a, o max ‚ FFFFFFF...
gdtr.base.s[segidx(0x1058)].c.type = 0xF2; // dpl=usuario, permite ler
e escrever
gdtr.base.s[segidx(0x1058)].c.bitsize = 0x40;
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
//Preenchendo o descritor(seletor) de pilha
gdtr.base.s[segidx(0x1060)].a.limit = header.stacksize-1; //o limite
est no cabecalho, -1 pois comeca em 0
gdtr.base.s[segidx(0x1060)].a.base = 0x01CC9866; //a base do
segmento a, o max ‚ FFFFFFF...
gdtr.base.s[segidx(0x1060)].b.base = 0x01CC9866; //a base do
segmento a, o max ‚ FFFFFFF...
gdtr.base.s[segidx(0x1060)].c.type = 0xF2; // dpl=usuario, permite ler
e escrever
gdtr.base.s[segidx(0x1060)].c.bitsize = 0x40;
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
//Colocando os dados depois de carregar o cabecalho
if(fread(&0x01989866, header.datasize, 1, exefile)!=1)
{ // fread(end da base, quantidade de dados,= )
fprintf(stderr,"Nao consigo ler os dados.\n");
exit(1);
}
//Colocando o codigo depois de carregar o cabecalho
if(fread(&0x01AA9866, header.codesize, 1, exefile)!=1) {
fprintf(stderr,"Nao consigo ler o codigo.\n");
exit(1);
}
fclose(exefile);
}
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
void criaTss() {
static struct tss estado;
//Descritor de Segmento para o TSS
gdtr.base.s[segidx(0x1068)].a.limit = sizeof(estado); //o limite do
segmento de pilha
gdtr.base.s[segidx(0x1068)].a.base = &estado; //
gdtr.base.s[segidx(0x1068)].b.base = &estado; //
gdtr.base.s[segidx(0x1068)].c.type = 0x89; //tipo do segmento. no
descriptor do segmento (p=1,dpl=00,s=0),
onde o s tem que ser 8.
gdtr.base.s[segidx(0x1068)].c.bitsize = 0x40; //0/0 do descrittor 32
bist?
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
// preenchimento da TSS
estado.eflags = 0x202; // PSW
estado.ldtr = 0x828; // eh assim mesmo
estado.iopb = sizeof(struct tss);
// todos os seletores com rpl=3=usuario
estado.cs = 0x1050+3; //codigo
estado.ds = 0x1048+3; //dados
estado.es = 0x1058+3; //variaveis
estado.gs = 0x1000+3; //ram de video
estado.ss = 0x1060+3; //Pilha
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
// preenchimento da TSS
asm mov eax,cr3; //recuperando o cr3 do SO
estado.cr3 = _EAX ;//estrutura de paginacao, coloco igual ao do SO
estado.eip = 0
;//codigo do usuario comeca em zero
estado.esp = (word)gdtr.base.s[segidx(0x1060)].a.limit + 1;//topo da
pilha, no limite
//para nao travar quando chegar uma interrupcao
estado.esp0 = _ESP;
asm mov ax,ss
estado.ss0 = _EAX ;
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
_far void sair(){
asm mov ax,0x930 // garantir espaco total para todos os segmentos
asm mov ds,ax
asm mov es,ax
asm mov fs,ax
exit(0);
}
/* -------------------------------------------------------------------------------------------SOFTWARE BASICO - carregador
-------------------------------------------------------------------------------------------*/
void criaCallGate() {
static word so_cs;
// seletor de codigo do S.O.
// preenchendo o call gate
// sair sera chamada pelo codigo do usuario
gdtr.base.g[segidx(0x1070)].a.offset = &sair;
gdtr.base.g[segidx(0x1070)].b.offset = &sair;
asm mov ax,cs
asm mov [so_cs],ax
gdtr.base.g[segidx(0x1070)].b.selector = so_cs;
gdtr.base.g[segidx(0x1070)].a.params = 0;
gdtr.base.g[segidx(0x1070)].a.type = 0xEC;
//no test.c (pode ser a 1a instrucao do main) temos que introduzir:
asm call 0x1070:0
}
int main() {
cadastrar(20111011);
/* Recupera alguns valores do S.O. para ficar em variaveis globais. */
asm sidt
asm sgdt
[idtr] // armazena inicio da IDT
[gdtr] // armazena inicio da GDT
/* Segmento de video */
descVideo();
initializar(5);
carregar("test"); // carrega o processo de usuario
criaTss();
criaCallGate();
// asm jmp 0x1050:0; // superjump: pula para outro segmento
asm jmp 0x1068:0; // hiperjump: pula para outro contexto (TSS)
return 0; //
}
/* -------------------------------------------------------------------------------------------APLICATIVO – Test.c
-------------------------------------------------------------------------------------------*/
// system call
#define systemcall asm call 0x1070:0
dword dummy; // definição de uma variavel apenas para preecher o
segmento correspondente (32 bits)
// prototipos
void desenhar_fractal();
void main() { // A primeira rotina do programa deve ser o main
desenhar_fractal();
systemcall;
}
// chamada ao S.O.
Segmentação - Passos
1. Observar a Tabela da GDT nos endereços 928, 930, .... E 810
- Busy).
(TR
2. Observar na Tabela de memória os segmentos de dados e de
código (Alt +D, Alt +C).
3. Executar descVideo() e observar na tabela da GDT a posição 1000.
4. Executar carregar(“test”) e observar o conteúdo da GDT em 1048,
1050, 1058, 1060.
5. Executar CriaTSS() e observar o conteúdo da GDT em 1068
(Available, Salva o contexto do aplicativo).
6. Executar CriaCallGate() e observar o conteúdo da GDT em 1070.
7. Executar JMP 0x1068:00 e observar a memória (tamanho do
segmento-Aplicativo), 1068 da GDT (Busy) e 810 (Available) e o
valor do EIP (0).
8. Executar no aplicativo o systemcall (call 0x1070:00).
Download

(Segmentação) ()