Иллюстрированный самоучитель по Assembler

Базовые средства программирования защищенного режима

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

Для того, чтобы наша программа могла бы хоть что-то сделать в защищенном режиме, для нее необходимо создать среду защищенного режима, в первую очередь, таблицу глобальных дескрипторов с описанием всех сегментов, с которыми программа будет работать. Кроме нас никто эту таблицу (при работе в DOS) не создаст. Таким образом, наша программа будет в какой-то мере выполнять функции операционной системы защищенного режима.

Для практического исследования защищенного режима придется выполнить некоторую работу по переконфигурированию компьютера. В наше время компьютеры обычно конфигурируются так, что при их включении сразу загружается система Windows. Работы, для которых требуется DOS, выполняются либо в режиме эмуляции DOS, либо в сеансе DOS, организуемом системой Windows. Для запуска прикладной программы защищенного режима такой способ не годится. Нам понадобится DOS в "чистом виде", без следов Windows.

Более того, перед запуском программы необходимо выгрузить все драйверы обслуживания расширенной памяти (HIMEM.SYS и EMM386.EXE) и программы, использующие расширенную память, например, SMARTDRV.EXE. Лучше всего загружать DOS с системной дискеты, подготовив файлы CONFIG.SYS и AUTOEXEC.BAT в минимальном варианте.

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

Пример 4.4. Программирование защищенного режима.

0.586Р; Разрешение трансляции всех команд МП 586
;Структура для описания дескрипторов сегментов
dcr struc; Имя структуры
limit dw 0; Граница (биты 0…15)
base_1 dw 0; База, биты 0…15
base_m db 0; База, биты 16…23
attr_1 db 0; Байт атрибутов 1
attr_2 db; Граница (биты 16…19) и атрибуты 2
base_h db 0; База, биты 24…31
dcr ends;
data segment use16;
;Таблица глобальных дескрипторов GDT
gdt_null dcr <0.0.0.0.0.0>; Селектор 0-обязательный нулевой дескриптор
gdt_data dcr <data_size-1.0.0.92h,0.0>; Селектор 8, сегмент данных
gdt_code dcr <code_size-1.0.0.98h,0.0>; Селектор 16, сегмент команд
gdt_stack dcr <511.0.0.92h,0.0>; Селектор 24, сегмент стека
gdt_screen dcr <4095,B000h,OBh,92h,0.0>; Селектор 32, видеобуфер
pdescr df 0; Псевдодескриптор для команды Igdt
data_size=$-gdt_null; Размер сегмента данных
data ends; Конец сегмента данных
text segment use16; Сегмент команд, 16-разрядный режим
assume CS:text,DS:data;
main proc;
xor EAX,EAX; Очистим ЕАХ
mov AX,data; Загрузим в DS сегментный
mov DS,AX; адрес сегмента данных
;Вычислим 32-битовый линейный адрес сегмента данных
;и загрузим его в дескриптор сегмента данных в GDT.
;В регистре АХ уже находится сегментный адрес.
;Умножим его на 16 сдвигом влево на 4 бита
shl ЕАХ,4; В ЕАХ линейный базовый адрес
mov EBP, ЕАХ; Сохраним его в ЕВР для будущего
mov BX,offset gdt_data; В ВХ адрес дескриптора
mov [BX].base_l,AX; Загрузим младшую часть базы
rol ЕАХ,16; Обмен старшей и младшей половин ЕАХ
mov [BX].base_m,AL; Загрузим среднюю часть базы
;Вычислим 32-битовый линейный адрес – сегмента команд
;и загрузим его в дескриптор сегмента команд в GDT
хог ЕАХ, ЕАХ; Очистим ЕАХ
mov AX,CS; Сегментный адрес сегмента команд
shl ЕАХ,4; В ЕАХ линейный базовый адрес
mov BX,offset gdt_code; В ВХ адрес дескриптора
mov [BX].base_l,AX; Загрузим младшую часть базы
rol ЕАХ,16; Обмен старшей и младшей половин ЕАХ
mov [BX].base_m,AL; Загрузим среднюю часть базы
;Вычислим 32-битовый линейный адрес сегмента стека
хог ЕАХ, ЕАХ; Все, как и для других
mov AX,SS; дескрипторов
shl ЕАХ,4
mov BX,offset gdt_stack
mov [BX].base_l,AX
rol EAX,16
mov [BX].base_m,AL
;Подготовим псевдодескриптор pdescr для загрузки регистра GDTR
mov dword ptr pdescr+2,EBP; База GDT
mov word ptr pdescr, 39; Граница GDT
Igdt pdescr; Загрузим регистр GDTR
cli;Запрет прерываний
;Переходим в защищенный режим
mov EAX,CR0; Получим содержимое CR0
or EAX,1; Установим бит защищенного режима
mov CRO,ЕАХ; Запишем назад в CR0
;---------------------------------------------------------;
;Теперь процессор работает в защищенном режиме;
;---------------------------------------------------------;
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.