Лабораторные работы    
 СОДЕРЖАНИЕ
 Введение
 1. Развитие архитектуры
 2. Структура МП
 3. Ресурсы МП
 4. Управление памятью
 5. Защита
 6. Многозадачность
 7. Прерывания и исключения
 8. Инициализация МП
 9. Эмуляция 8086
 Глоссарий
 ПРАКТИКА
 1. Семантический разрыв
 2. CPUID
 3. Защищенный режим
 Вопросы и задания

3. Исследование работы IA-32 в защищенном режиме

Цель работы: Познакомится с особенностями написания программы для защищенного режима. На примере конкретной программы пронаблюдать механизмы формирования линейного адреса в различных режимах работы процессора.

Теоретическая часть

Основным режимом работы 32-битных процессоров семейства IA-32 является защищенный. В реальном режиме происходит лишь инициализация системы, иногда он используется для выполнения старых приложений для процессоров 8086/88 и 80286. Механизмы защиты, многозадачность, страничное преобразование, полноценное выполнение 32-битного кода и многие другие возможности 32-битных процессоров доступны лишь в защищенном режиме.

Прежде, чем перевести процессор в защищенный режим, следует подготовить дескрипторные таблицы (глобальную и для прерываний), а также таблицы, необходимые для страничного преобразования (если система собирается его использовать). Переход в защищенный режим происходит после выставления младшего бита в регистре CR0 (MSW), затем следует выполнить далекий межсегментный переход (FAR JUMP) для очистки кэша команд:

MOV EAX,1
MOV CR0,EAX
JMP DWORD PTR [PMEntry]

При использовании 32-битной операционной системы для защищенного режима пользовательским программам нет необходимости в таких действиях. Среду для защищенного режима подготавливает сама операционная система. Прикладная программа может считать, что уже работает в линейном 4Гбайтном пространстве.
Пример для Windows (tasm32)Пример для Linux (nasm)
.386
; "плоская" модель - для защищенного режима
MODEL FLAT 

.DATA  ; сегмент данных
Msg DB "Hello, world",0

.CODE  ; сегмент кода
Entry: ; точка входа в программу
  SUB EBX,EBX

  PUSH EBX ; флаги (0=MB_OK)
  PUSH EBX ; адрес текста заголовка
  PUSH OFFSET Msg ; адрес контента
  PUSH EBX ; дескриптор окна
; вызов WinAPI MessageBox(NULL,Msg,NULL,MB_OK)
  CALL MessageBoxA 

  PUSH EBX ; код возврата
; вызов WinAPI ExitProcess(0)
  CALL ExitProcess 

  END Entry
  section .data ; сегмент данных
Msg: DB "Hello, world",10

  section .code ; сегмент кода
  global _start
_start: ; точка входа в программу
  MOV ECX,Msg ; адрес буфера
  MOV EDX,13 ; длина сообщения
l1:
  MOV EBX,1 ; дескриптор файла (stdout)
; вызов write(1,Msg,13)
  MOV EAX,4
  INT 80h
  CMP EAX,-4096
  JA skip ; в EAX кол-во выведенных байт
  ADD ECX,EAX
  SUB EDX,EAX
  JNZ l1 ; при необходимости выводим остаток
skip:
  SUB EBX,EBX ; код возврата
; вызов exit(0)
  MOV EAX,1
  INT 80h
  HLT

Если операционная система не предназначена для работы в защищенном режиме (например, DOS), можно использовать различные системные средства для перехода в защищенный режим. Наиболее предпочтительны следующие средства (в порядке уменьшения предпочтительности):

  1. DPMI - DOS Protected Mode Interface (реализован в DOS/4G, Quarterdeck DPMI, Borland DOS Extender, а также во всех версиях Windows).
  2. VCPI - Virtual Control Program Interface (реализуется драйвером EMS).
  3. INT 15h (реализуется BIOS).

DPMI обеспечивает программам для DOS доступ к памяти выше 1Мб, предоставляя программный интерфейс к некоторым функциям BIOS и DOS в защищенном режиме. Этот интерфейс содержит функции, позволяющие программам в защищенном режиме резервировать память, дескрипторы, вызывать код в режиме V86.

Прежде, чем воспользоваться сервисами DPMI, программа должна переключиться в защищенный режим с помощью предназначенной для этого функции. Для перехода в защищенный режим программа должна сделать межсегментный вызов (FAR CALL) по адресу, возвращаемому функцией:

MOV AX,1687h
INT 2Fh

Если DPMI присутствует, и вызов прошел успешно, AX=0, DX содержит версию DPMI, SI содержит количество параграфов, необходимых для служебных данных DPMI, а ES:DI - адрес процедуры переключения в защищенный режим. В случае ошибки AX - не ноль. Перед тем, как вызвать процедуру переключения, программа резервирует память указанного размера и помещает в ES соответствующий сегментный адрес.

TEST AX,AX
JNZ Error
MOV [PM_Entry+2],ES
MOV [PM_Entry],DI
MOV BX,SI
MOV AH,48h
INT 21h ; резервируем память под служебные данные DPMI
; перед использованием функции 48h
; программа должна вернуть DOS неиспользуемую память
; при помощи функции 4Ah
MOV ES,AX

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

SUB AX,AX
CALL DWORD PTR [PM_Entry]
JC Error

Если переключение прошло успешно, флаг переноса (CF) равен 0. Программа работает в защищенном режиме. Сегментные регистры содержат селекторы дескрипторов сегментов с соответствующими базовыми адресами и пределами в 64К (ES содержит селектор сегмента с PSP, его предел - 256 байт). В дальнейшем доступны сервисы DPMI, которые вызываются при помощи программного прерывания INT 31h. Завершение программы защищенного режима возможно при помощи функции AH=4Ch прерывания INT 21h. Спецификация DPMI декларирует доступность лишь этой функции DOS. Однако многие реализации, например, DPMI в Microsoft Windows, обеспечивают функционирование и других функций DOS (01h-0Ch - ввод с клавиатуры, вывод на экран; 39h-43h - работа с файлами и каталогами и некоторые другие).

Вот некоторые сервисы DPMI INT 31h (подробнее см. Tech! Help v.6.0):

Номер функции
(значение AX)
Назначение
0000hЗарезервировать дескриптор в LDT
0001hОсвободить дескриптор в LDT
0002hКонвертировать сегмент реального режима в дескриптор
0006hПолучить базовый адрес сегмента
0007hУстановить базовый адрес сегмента
0008hУстановить предел сегмента
0009hУстановить права доступа дескриптора
000BhПолучить дескриптор
000ChУстановить дескриптор
0100hЗарезервировать память в DOS
0101hОсвободить память в DOS
0102hИзменить размер памяти, зарезервированной в DOS
02xxhПолучение и установка прерываний и исключений для реального и защищенного режима
0300hВызов программного прерывания в реальном режиме
0301h - 0302hВызов процедуры в реальном режиме
0303hЗарезервировать новый шлюз переключения из реального в защищенный режим
0304hОсвободить шлюз переключения из реального в защищенный режим
0306hПолучить шлюзы переключения между режимами
0400hПолучить версию DPMI
0500hПолучить информацию о свободной памяти
0501hЗарезервировать блок памяти
0502hОсвободить блок памяти
0503hИзменить размер зарезервированного блока памяти
06xxhУправление подкачкой
и др.

Задание:

1) Напишите программу для Windows или для Linux, выводящую значения сегментных регистров. По этим значениям выясните уровень привилегий, с которым запущена ваша программа, а также в какой дескрипторной таблице содержатся дескрипторы, соответствующие селекторам.

Для того, чтобы использовать в программе вызовы Windows API, в тексте программы следует определить соответствующие символы как внешние, с помощью следующих директив ассемблера:

INCLUDELIB import32.lib
EXTRN MessageBoxA:NEAR
EXTRN ExitProcess:NEAR

При компиляции программы, используйте опцию /ml для того, чтобы в объектный файл эти символы были включены с учетом регистра. Компоновщику TLINK32 следует указать опцию /Tpe, отвечающую за генерацию исполняемого файла для Win32. При необходимости также укажите при помощи /L путь к библиотеке import32.lib (например, D:ASMLIB).

Стандартной для Linux ассемблерной семантикой является семантика AT&T, которая существенно отличается от принятой Intel (например, TASM/MASM для DOS и Windows). Однако существуют и средства для использования семантики Intel: as86 или nasm. В данной работе приведены примеры для использования nasm. Чтобы транслировать исходный текст test32.asm в исполняемый файл, необходимы следующие команды:

nasm -f elf test32.asm
ld test32.o -o test32

Опция -f в команде nasm указывает формат выходного файла - ELF (executable linux format). В результате работы ассемблера nasm получается объектный файл test32.o, который необходимо обработать редактором связей ld. Опция -o в команде ld задает имя выходного файла. Если ее не указывать, исполняемый файл будет записан в a.out.

2) Напишите программу для DOS, которая использует DPMI для переключения в защищенный режим. После переключения программа получает дескриптор, соответствующий...

Вариант N1 ...сегменту кода,...
Вариант N2 ...сегменту данных,...
Вариант N3 ...сегменту стека,...
Вариант N4 ...сегменту ES,...

...а затем выводит содержимое дескриптора и сравнивает его базовый адрес со значением в сегментном регистре в реальном режиме.

При написании этой программы придется использовать функцию 000Bh сервиса DPMI. Входные параметры:
AX=000Bh;
BX - селектор запрашиваемого дескриптора;
ES:DI - указатель на 8-байтный буфер под дескриптор;

После успешного выполнения функции флаг переноса (CF) должен быть очищен.

Для вывода на экран можно использовать функцию DOS AH=09h INT 21h.

Контрольные вопросы:

  1. Каков формат селектора сегмента? По результатам выполнения программ в заданиях 1 и 2 выясните, с каким уровнем привилегий выполняется ваша программа в защищенном режиме, в какой дескрипторной таблице хранятся соответствующие дескрипторы.
  2. Как задается базовый адрес сегмента в реальном и защищенном режиме?
  3. Как задается предел сегмента в реальном и защищенном режиме?
  4. Каков формат дескриптора сегмента? По результатам выполнения программы в задании 2 выясните: тип дескриптора, уровень привилегий дескриптора, атрибуты сегмента, базовый адрес сегмента, предел сегмента.