Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Финогенов-основы_языка_ассемблера.doc
Скачиваний:
46
Добавлен:
17.09.2019
Размер:
3.35 Mб
Скачать

Глава 4

Атрибут сегмента, действующий по умолчанию, можно изменить на противоположный с помощью префиксов замены размера операнда (66h) и замены размера адреса (67h). Таким образом, для сегмента с D=0 пре­фикс 66U перед некоторой командой заставляет ее рассматривать свои операнды, как 32-битовые, а для сегмента с D=l тот же префикс 66h, наоборот, сделает операнды 16-битовыми. В некоторых случаях транслятор сам включает в объектный модуль необходимые префиксы, в других слу­чаях их приходится вводить в программу «вручную».

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

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

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

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

Пример 4-4. Программирование защищенного режима .586Р разрешение трансляции всех команд МП 586

;Структура для описания дескрипторов сегментов

dcr struc limit dw base_ldw basc_m db attr Idb

;Имя структуры ;Граница (биты 0...15) ;База, биты 0...15 ;База, биты 16...23 ;Байт атрибутов 1

уширенные возможности современных микропроцессоров

187

;Граница (биты 16...19) и атрибуты 2 ;База, биты 24...31

attr_2db О

baseji db О

dcr ends ;

data segment use!6 ;

;Таблица глобальных деифипторов GOT

gdt_null dcr <0,0,0,0,0,0> ;Селектор О -обязательный

;нулевой дескриптор

gdt_data dcr <data_size-l,0,0,92h,0,0> ;Селектор 8,

;сегмент данных

gdt_code dcr <сос!е_817е-1,0,0,98п,0,0>;Селектор 16,

;сегмент команд

gdt_stack dcr <511,0,0,92h,0,0> ;Селектор 24 —

;сегмент стека

gdt_screen dcr <4095,8000h,OBh,92h,0,0> ;Селектор 32,

видеобуфер

pdescr df 0 ; Псевдодескриптор для команды Igdt

data_size=:S-gdt_iiull ;Размер сегмента данных

data ends ;Конец сегмента данных

text segment use!6 ;Сегмент команд, 16-разрядный режим

assume CS:text,DS:data;

main proc ;

xor EAX,EAX ;Очистим ЕАХ

mov AX,data ;3агрузим в DS сегментный

mov DS,AX ;адрес сегмента данных

;Вычислим 32-битовый линейный адрес сегмента данных

;и загрузим его в дескриптор сегмента данных в GDT.

;В регистре АХ уже находится сегментный адрес.

;Умножим его на 16 сдвигом влево на 4 бита

shl ЕАХ,4 ;В ЕАХ линейный базовый адрес

mov ЕВР,ЕАХ ;Сохраним его в ЕВР для будущего

mov BX,offset gdt_data ;B BX адрес дескриптора

mov [BX].base_I,AX ;3агрузим младшую часть базы

rol ЕАХ,16 ;Обмен старшей и младшей половин ЕАХ

mov [BX].base_m,AL;3arpy3HM среднюю часть базы

;Вычислим 32-битовый линейный адрес сегмента команд

;и загрузим его в дескриптор сегмента команд в GDT хог ЕАХ,ЕАХ ;Очистим ЕАХ

mov AX,CS ;Сегментный адрес сегмента команд

shl ЕАХ,4 ;В ЕАХ линейный базовый адрес

mov BX,offset gdt_code ;В ВХ адрес дескриптора . mov [BX].base_I,AX;3arpy3HM младшую часть базы rol ЕАХ, 16 ;Обмен старшей и младшей половин ЕАХ

mov [BX].base_m,AL;3arpy3HM среднюю часть базы

;Вьгчислим 32-битовый линейный адрес сегмента стека хог ЕАХ,ЕАХ ;Все, как и для других

mov AX,SS дескрипторов

shl EAX,4

188

Глава -t

mov BX,offset gdt_stack

mov {BX].base_l,AX

rol ЕАХД6

mov [BX].base_m,AL ;Подготовим псевдодескриптор pdescr для загрузки регистра GDTR

mov dword ptr pdescr+2,EBP ;База GOT

mov word ptr pdescr,39 ;ГраницаООТ

Igdt pdescr ;3агрузим регистр GDTR

cli ;3апрет прерываний

; Переходим в защищенный режим

mov EAX,CRO ;Получим содержимое CRO

or EAX,1 ;Установим бит защищенного режима

mov CRO,EAX ;3апишем назад в CRO

; Теперь процессор работает в защищенном режиме ; ? ,

;3агружаем в CS:IP селектор смещение точки continue

db OEAh ;Код команды far jmp

dw offset continue ;Смещение

dw 16 ;Селектор сегмента команд

continue: ;Делаем адресуемыми данные

mov АХ,8 ;Селектор сегмента данных

mov DS,AX ;3агрузим в DS

;Делаем адресуемым стек

mov mov

АХ,24 SS,AX

;Селектор сегмента стека ;3агрузим в SS

Инициализируем ES и вьшодим символ

mov AX,32 ;Селектор сегмента видеобуфера

mov ES,AX ;3агрузим в ES

mov BX,2000 ;Начальное смещение на экране

mov AX,09FOFh ;Символ с атрибутом mov ES:[BX],AX ;Вывод в видеобуфер ;Вернемся в реальный режим

; Установим ;значение границы ;для реатъного ;режима

;3агрузим теневой регистр

;сегмента данных

mov gdt_data.limit,OFFFFh mov gdt_code.limit,OFFFFh

mov mov mov mov mov mov mov mov

gdt_stack.limit,OFFFFh

gdt_screen. limit, OFFFFh

AX, 8

DS,AX

;То же для

; стека

;То же

;для регистра ES

АХ,24 SS,AX АХ,32 ES,AX

;Выполним дальний переход, чтобы заново загрузить ;селектор в CS и модифицировать его теневой регистр

Расширенные возможности современных микропроцессоров

189

db OEah ;Код команды jmp far

dw offset go ;Смещение точки перехода

dw 16 ;Селектор сегмента команд

;Переключим режим процессора

go: mov EAX,CRO ;Получим содержимое CRO

and EAX,OFFFFFFFEh;C6pocHM бит РЕ mov CRO,EAX ;3апишем назад в CRO

db OEah ;Код команды far jmp

dw offset return ;Смещение точки перехода

dw text ;Сегментный адрес

^ ^

; Теперь процессор снова работает в реальном режиме ;

^ ^

; Восстановим операционную среду реального режима

return: mov AX,data mov DS,AX mov AX,stk SS,AX SP,512

mov mov sti mov

AX.4COOU

;3агрузим сегментный ;регистр DS ;3агрузим сегментный ;регистр SS восстановим SP ;Разрешим прерывания ;3авершим программу ;обычным образом

2Ih

int

;Размер сегмента команд ; Конец сегмента команд ; Сегмент ; стека

main endp code_size=S -main text ends stk segment stack

db 512 dup О stk ends

;Конец программы и точка входа

Для того, чтобы разрешить использование всех, в том числе привиле­гированных команд 32-разрядных процессоров, в программу включена директива .586Р.

Программа начинается с объявления структуры dcr, с помощью кото­рой будут описываться дескрипторы сегментов. Сравнивая описание струк­туры dcr в программе с рис. 4.9, нетрудно проследить их соответствие друг другу. Для удобства программного обращения в структуре dcr база описы­вается тремя полями: младшим словом (base_l) и двумя байтами: средним (base_m) и старшим (base_h).

В байте атрибутов 1 задается ряд характеристик сегмента. В примере 4.4 используются сегменты двух типов: сегмент команд, для которого байт attr_l должен иметь значение 98h (присутствующий, только исполнение, DPL=0), и сегмент данных (или стека) с кодом 92п (присутствующий, чтение и запись, DPL=0).

Некоторые дополнительные характеристики сегмента указываются в старшем полубайте байта attr_2. Для всех наших сегментов значение этого


end main

190