Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org

Protected Mode

by Marius Marcu

Memory Managment

Ключ к пониманию Protected Mode лежит в адресации памяти. Почти все расширенные возможности процессора основаны на этом. Многозадачность , привилегии , доступ к 4 гигам памяти происходят именно отсюда.

Для 286 с его 24 адресными линиями и 16-битными регистрами , доступ к 4 GB невозможен. Эти возможности появились в 386.

Виртуальная адресация

Сегменты в защищенном режиме можно разбить на кодовые и сегменты данных. В отличие от реального режима , процессор рассматривает память виртуально, что означает,что про реальные физические адреса программы понятия не имеют.

По необходимости , операционная система может поместить код или данные на диск. Виртуальный адрес - 16-битный селектор плюс 32-битное смещение. Сначала селектор должен быть загружен в один из сегментных регистров - CS, DS, ES, FS или GS, а затем уже грузится смещение внутри этого сегмента.

Также нужно понимать тот факт , что селектор - это не реальный адрес памяти. Это индекс сегментного дескриптора в специальной таблице , или указатель на реальный адрес . А уже этот адрес, помимо реального физического содержания, содержит в себе дополнительные битовые атрибуты , характеризующие данный сегмент, размер сегмента. И уже окончательный адрес памяти строится как комбинация селектора плюс смещения

Дескрипторы

Дескриптор - это специальная структура.Его размер = 8 байт. Его атрибуты :
     * реальный физический стартовый адрес сегмента (32 Bit)
     * длина сегмента (20 Bit)
     * дополнительные биты : права , тип и т.д.
 
Следующая картинка показывает дескриптор 80386 :

Дополнительная битовая информация о сегменте хранится в 6 и 7 байтах. 6- байт :

Поле TYPE определяет тип сегмента и набор разрешенных операций:

Следующая таблица дает набор возможных комбинаций типов сегментов :

Номер Значение TYPE Тип сегмента
0 000b Datasegment (read only)
1 001b Datasegment
2 010b reserved
3 011b "expand down" Datasegment
4 100b Codesegment (not readable, execute only)
5 101b Codesegment
6 110b "Conforming"-Codesegment (not readable, execute only)
7 111b "Conforming"-Codesegment

Дополнительная информация хранится в 7-м байте :

Пример дескриптора

  Создадим дескриптор со следующими характеристиками :
     * стартовый физический адрес сегмента -  01F2E3Dh
     * длина сегмента - 2 метра (2097152d=200000h)
     * это сегмент данных (читаемый и записываемый)
     * DPL= 2
     * тип сегмента - 80386-segment
 
Напишем несколько строк асм-кода :
  my_descriptor:  dw 0200h            ; размер сегмента (bit 0..15)
                  dw 2E3Dh            ; базовый адрес сегмента (bit 0..15)
                  db 1Fh              ; базовый адрес сегмента (bit 16..23)
                  db 11010010b        ; доступ и тип 
                  db 11000000b        ; дополнительная информация и размер (bit 16.19) 
                  db 0                ; базовый адрес сегмента (bit 24..31) 
 
Первое слово в дескрипторе - размер сегмента. Он у нас 2 метра . Поскольку размер сегмента больше метра , устанавливаем бит granularity в единицу - т.е. размер страницы памяти равен теперь 4 KB (это в 7-м байте).

Поскольку размер в 2 MB характеризует т.н. большой сегмент , нужно выполнить 3 условия :

         
   1. Тип сегмента - 80386 (контролируется битом B в байте 7).
   2. Бит Granularity нужно установить в 1 для постраничной организации 
      размером 4096 byte (G-бит в байте 7).
   3  Длину сегмента нужно сконвертировать в формат 4 KB unit 
   	(т.е. разделить размер сегмента на 4096).
         2 MB= 2097152d / 4096d=512d= 200h.
 
Второе слово - это биты с 16 по 32 - содержат базовый адрес сегмента (в данном случае младшее слово в адресе 001F 2E3Dh, т.е. 2E3Dh)

Третье слово состоит из 2-х байтов. нижний байт включает биты 16..23 базового адреса сегмента (в нашем примере: 1Fh).Старший байт включает параметры доступа и типа :

 	 
 	 Биты доступа / типа : 1 10 1 001 0:
 	o первый бит слева - сегмент доступен
 	o следующие 2 бита - уровень привилегии  (10 = уровень 2).
 	o следующий бит=1 - это тип - сегмент
 	o следующие 3 бита - поле TYPE - сегмент типа 1 (data segment, reading + writing)
 	o последний бит - ACCESS = 0 
 
4-е слово состоит из 2-х байтов. Старший , 8-й байт , включает биты 24..31 базового сегментного адреса, в нашем случае (001F 2E3Dh). 7-й байт включает : 16..19 - биты длины сегмента.

Дескрипторные таблицы

Дескрипторы сводятся в линейную таблицу. В такой таблице может быть не более 8192 дескрипторов ( 64 KB (65536) / 8 = 8192)

"Global Descriptor Table" - GDT .
"Interrupt Descriptor Table" - IDT - включает специальные дескрипторы - гейты - Gates. Гейт используется для хранения адреса процедуры прерывания. Операционная система обязана обрабатывать любое потенциальное исключение. Также дескрипторную таблицу можно создать для любой задачи - это будет LDT.

В следующем примере показаны 3 дескриптора таблицы GDT :

      descriptor_0 db 8 dup (?)          
      descriptor_1 db 8 dup (?)          
      descriptor_2 db 8 dup (?)
  
Адрес Самой GDT надо загрузить в регистр GDTR :
     GDTSTRUC STRUC                   
 	 Limit    dw ?                   
 	 BaseAddr dd ?          
     GDTSTRUC ENDS           
 	 
 	 gdt_adr  GDTSTRUC ?  
 	
 	; определим размер Global Descriptor Table 	 		      
 	; размер GDT = 3*8 42 байта
          mov [ gdt_adr.Limit ], 3*8  
 	
 	; установим базовый адрес
 	; преобразование логического адресатипа segment:offset
 	; в 32-битный линейный адрес
 	xor eax,eax           
 	mov ax,seg descriptor_0           
 	shl eax,4           
 	add eax,offset descriptor_0           
 	mov [ gdt_adr.BaseAdr ],eax  
 	; загружаем регистр GDTR 
 	lgdt gdt_adr
  

Селектор

Виртуальный адрес состоит из 2-х частей - селектора и смещения. Смещение мы только что рассмотрели. Селектор имеет бит TI ("Table Indicator") , который указывает либо на GDT , либо на LDT. Также имеется бит RPL ("Requested Privilege Level") - бит уровня привилегий :

Рассмотрим селектор :

 	Selector: 02FBh (binary: 0000001011111011b)            
 	TI bit =  0  ==> таблица GDT           
 	RPL    = 11b ==> уровень привилегий (3)           
 	Index  = 0000001011111b = 05Fh
 
Для селектора есть особенность - он не может быть загружен напрямую в селектор командой MOV. А обойти это можно так :
 	MOV AX,02FBh  
 	MOV DS,AX
 

Инициализация защищенного режима

Интеловские процессоры при загрузке начинают работать в Realmode . Protected Mode нужно активировать. Для этого нужно установить бит PE регистра CR0. Это нельзя сделать напрямую с помощью команды MOV. Это можно сделать так :
 	mov eax,cr0
 	or  eax,1       ;  PE=1
 	mov cr0,eax	
 
Перед установкой бита PE нужно проинициализировать GDT . Также необходимо проинициализировать IDT , которая будет обрабатывать исключения и прерывания. Для непосредственного перехода из real mode в protected mode нужно сделать т.н. FAR-JMP (например JMP 02FB:0000).

IDT

Концепция защиты подразумевает , что пользовательские программы выполняются на ином уровне привилегий , нежели операционная система. Ошибка внутри пользовательской программы не должна затрагивать работу самой операционной системы.

Для того чтобы пользовательский процесс общался с операционной системой , существуют гейты. Существуют 4 основных типа гейтов :

Gate Function
Call Вызов системной подпрограммы
Interrupt прерывания как от железа , так и от софта (INT)
Trap также 2 типа : hardware Interrupts и INT-инструкции
Task команды: CALL, JMP, INT и hardware Interrupts)

Гейты trap и interrupt отличаются только битом IF ("Interrupt Enable Flag") флагового регистра. Гейт interrupt сначала обнуляет этот бит , потом восстанавливает его после команды IRET. Гейт trap его вообще не трогает.

Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье