Gdt
В интеловской архитектуре для защищенного режима контроль за памятью осуществляется
с помощью специальных дескрипторных таблиц .
Дескриптор может хранить информацию о каком-то обьекте - задаче , программе и т.д.
Перед тем как вы каждый раз делаете запись в сегментный регистр , процессор должен
проверить корректность такой записи .
Intel определяет 3 типа таблиц : таблица прерываний - IDT,
глобальная таблица дескрипторов - GDT , и локальная таблица дескрипторов - LDT.
Таблицы инициализируются с помощью инчструкций
lidt, lgdt, lldt.
Положение этих таблиц фиксируется еще на этапе загрузки и последующий доступ к ним
осуществляется с помощью указателей .
Glossary
- Segment
-
область памяти с заданными свойствами
- Segment Register
-
регистр , ссылающийся на такой сегмент
( ss, cs, ds ...)
- Selector
-
ссылка на дескриптор , загружаемый в сегментный регистр
.
- Descriptor
-
структура (строка в таблице)
Что можно сохранить в GDT ?
- null descriptor
- code segment descriptor (type=0x9A)
- data segment descriptor (type=0x92)
- TSS segment descriptor
GDT имеет следующую структуру :
- null descriptor
- dpl 0 code segment descriptor
- dpl 0 data segment descriptor
- dpl 3 code segment
- dpl 3 data segment
- остальной произвольный набор дескрипторов
dpl 0 code segment загружается в MSR.
Остальные вычисляются на его базе .
(See the intel instruction reference for SYSENTER and SYSEXIT for more information.)
Flat Setup
Если вам нужны 4GB памяти :
GDT[0]={.base=0, .limit=0, .type=0}; // selector 0 cannot be used
GDT[1]={.base=0, .limit=0xffffffff, .type=0x9A}; // selector 8 will be our code
GDT[2]={.base=0, .limit=0xffffffff, .type=0x92}; // selector 0x10 will be our data
GDT[3]={.base=&myTss, .limit=sizeof(myTss), .type=0x89}; // you can use LTR(0x18)
В данной модели код не очень-то и защищен , потому-что он перекрывается с сегментом данных.
Small Kernel Setup
Если сегменты кода и данных нужно разделить и каждому выделить допустим по 4 метра:
GDT[0]={.base=0, .limit=0, .type=0}; // selector 0 cannot be used
GDT[1]={.base=0x04000000, .limit=0x03ffffff, .type=0x9A}; // selector 8 will be our code
GDT[2]={.base=0x08000000, .limit=0x03ffffff, .type=0x92}; // selector 0x10 will be our data
GDT[3]={.base=&myTss, .limit=sizeof(myTss), .type=0x89}; // you can use LTR(0x18)
Начало кодового сегмента будет начинаться с отметки 4 метров иметь адрес совпадающий с cs:0 ,
сегмент данных будет начинаться с 8 метров и совпадать с адресом ds:0.
0. Отключение прерываний
Прерывания нужно отключать дабы не было проблем.
1. Заполнение таблиц
Базовый адрес в таблице GDT[] состоит из 3-х частей плюс флаг для установки свойств.
encodeGdtEntry(unsigned char target[8], struct MTGDT source)
{
if ((source.limit>64K) && (source.limit&0xfff)!=0xfff))
kerror("you can't do that!");
if (source.limit>64K) {
// adjust granularity if required
source.limit=source.limit/4096;
target[6]=0xC0;
} else target[6]=0x40;
target[0]=source.limit&0xff;
target[1]=(source.limit>>8)&0xff;
target[6]|=(source.limit>>16)&0xf;
target[2]=source.base&0xff;
target[3]=(source.base>>8)&0xff;
target[4]=(source.base>>16)&0xff;
target[7]=(source.base>>24)&0xff;
target[5]=source.type;
}
2. Инициализация таблиц
Это можно сделать с помощью команд lgdt и lidt
real mode
линейный адрес может быть вычислен кака segment*16+offset.
gdtr dw 0 ; for limit storage
dd 0 ; for base storage
setGdt:
xor eax,eax
mov ax, ds
shl eax, 4
add eax, GDT
mov [gdtr+2],eax
mov eax, GDT_end
sub eax, GDT
mov [gdtr],ax
lgdt [gdtr]
ret
flat protected mode
gdtr dw 0 ; for limit storage
dd 0 ; for base storage
setGdt:
mov eax,[esp+4]
mov [gdtr+2],eax
mov ax,[esp+8]
mov [gdtr],ax
ldgt [gdtr]
ret
3. Reload segment registers
Для работы с GDT нужно использовать сегментные регистры
reloadSegments:
jmp 0x08:here
.here:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
ret
LDT
Аналогично GDT (global descriptor table), LDT (local
descriptor table) состоит из дескрипторов .
Каждый процесс имеет свою собственную LDT .
GDTR (base+limit)
+-- GDT -----------+
| |
SELECTOR ---> [LDT descriptor ]----> LDTR (base+limit)
| | +---LDT-------------+
| | | |
.. .. .. ..
+------------------+ +-------------------+
Сегменты
Real mode
В RealMode адрес имеет форму A:B :
Physical address = (A * 0x10) + B
Регистры в real-mode при адресации ограничены 16 битами.
16 бит - это число в диапазоне от 0 до 64k.
Эти 64К и называются сегментом.
A = A 64k сегмент
B = смещение внутри сегмента
Базовые адреса сегментов - это чила типа (A * 0x10) .
Т.е. сегмент 0x1000 имеет базовый адрес 0x10000.
Этот сегмент простирается в диапазоне 0x10000 ->
0x1FFFF, соответственно сегмент 0x1010 имеет базовый адрес 0x10100 и занимает диапазон
физических алресов 0x10100 -> 0x200FF
Имеются 6 сегментных регистров : (CS, DS, ES, FS, GS, SS).
CS = Code Segment
DS = Data Segment
SS = Stack Segment
ES = Extra Segment
FS/GS = General Purpose Segments
DS,ES,FS,GS,SS можно смело использовать для работы с памятью .
MOV [SI], AX - базовым сегментным регистром по умолчанию является DS
MOV ES:[DI], AX - здесь базовым сегментным регистром является es
Операции с сегментными регистрами
Кроме CS,
сегментные регистры можно загружать из AX (mov ds, ax) или из стека (pop ds).
CS нельзя изменить командой.
Его можно изменить при переключении на другой сегментный регистр.
- Far Jump
- Например JMP 0x10:0x100 грузит CS сегментом 0x10
и IP = 0x100. CS:IP - это логический адрес для инструкции.
- INT
- Новое значение CS/IP читается из таблицы Interrupt Vector Table
.
Protected Mode
Здесь логический адрес используется в форме A:B.
Регистры в этом режиме ограничены 32 битами , что дает доступ к 4 гигам памяти.
Отличие защищенного режима от реального в том , что А -
это не абсолютное значение , это - selector, который есть смещение в таблице Global Descriptor Table(GDT).
GDT состоит из набора таких дескрипторов .
Каждый дескриптор включает в себя следующую информацию :
- Базовый адрес сегмента
- Тип сегмента (16-bit/32-bit)
- Привилегия (Ring 0 -> Ring 3)
- Байтовое ограничение (Segment limit is in byte/4kb units)
- Сегментное ограничение (The maximum legal offset within the segment)
- Тип дескриптора (0 = system; 1 = code/data)
- Еще один тип(Code/Data/Read/Write/Accessed/Conforming/Non-Conforming/Expand-Up/Expand-Down)
Диапазон физических адресов в сегменте:
Segment Base -> Segment Base + Segment Limit
Physical address = Segment Base (Found from the descriptor GDT[A]) + B
|
Ольга | Всё в этой статье вроде и не плохо,но я,задав в поисковой строке idt,не обнаружила того,что меня интересует. 2006-03-30 11:40:27 | Яковлев Се� | Если набрать в поисковой строке "idt", то будет выведен список из 30 страниц.
В том числе и эта страница.
.
2006-03-30 19:33:19 | |
|