|
|
Для создания программ, работающих в защищённом режиме, фирмы Microsoft, Intel, IBM, Lotus, Phar Lap, Rational Systems, Borland, Quarterdeck разработали интерфейс с защищённым режимом - DPMI (DOS Protected Mode Interface). Пользуясь этим интерфейсом, программы, стартующие как обычные DOS-программы реального режима, могут переключиться в защищённый режим и работать с расширенной или даже виртуальной памятью. Интерфейс DPMI обеспечивается специальной программой, называемой сервером DPMI. Сервером может быть отдельная резидентная программа, либо средства для поддержки DPMI могут входить в состав операционной системы (например, WINDOWS и OS/2 версии 2.0 позволяют работающим под их управлением DOS-программам использовать интерфейс DPMI). В этом разделе мы кратко опишем функции DPMI, а в разделе, посвященном виртуальной машине WINDOWS, приведём пример программы, работающей в защищённом режиме с использованием функций DPMI спецификации 0.9. Спецификация DPMI версии 0.9 поддерживается операционной системой WINDOWS версий 3.0 и 3.1, работающей в расширенном режиме на процессорах i80386 или i80486. Все функции DPMI реализованы в рамках прерывания INT 31h, обработчиком этого прерывания является сервер DPMI. Прежде чем использовать функции DPMI, программа с помощью описанных ниже функций прерываний INT 2Fh должна убедиться в присутствии поддержки DPMI, получить адрес процедуры переключения в защищённый режим и выполнить это переключение. Программа должна вызывать прерывание INT 31h после переключения в защищённый режим, в реальном режиме это прерывание вызывать нельзя. Получить адрес перехода в защищённый режим С помощью этой функции программа может определить наличие в системе интерфейса DPMI и получить адрес процедуры перехода в защищённый режим работы. Для вызова этой функции необходимо использовать прерывание INT 2Fh, загрузив регистр AX следующим образом: Регистры на
входе: Если функция была успешно выполнена, в регистры будут записаны следующие значения: Регистры
на выходе: Если выполнение функции закончилось с ошибкой, содержимое регистра AX не равно нулю. Вход в защищённый режим После того, как программа получила адрес процедуры для входа в защищённый режим, она может вызвать эту процедуру при помощи команды CALL. Перед вызовом необходимо загрузить регистры: Регистры на
входе: После загрузки регистров необходимо выполнить вызов процедуры с адресом, который был получен в регистрах ES:DI после вызова предыдущей функции. Если функция выполнилась успешно, флаг CARRY сброшен и программа выполняется в защищённом режиме. Регистры на
выходе Остальные регистры не изменяются. Если функция выполнилась с ошибкой, флаг CARRY устанавливается в единицу и программа продолжает выполнение в реальном режиме. После входа в защищённый режим вам становится доступен интерфейс DPMI через функции прерывания INT 31h. Для завершения своей работы программа, использующая DPMI, должна выдать прерывание INT 21h (функция 4Ch) - это обычный способ завершения программ, работающих в среде MS-DOS. Приведём фрагмент программы, использующей DPMI. На примере этого фрагмента мы покажем, как убедиться в том, что в системе имеется интерфейс DPMI, как войти в защищённый режим и завершить работу программы. ; Получаем адрес
точки входа в защищённый режим Определение текущего режима работы Если ваша программа может работать и в реальном режиме и в защищённом, с помощью этой функции вы можете определить текущий режим работы. Для выполнения функции необходимо вызвать прерывание INT 2Fh, предварительно загрузив регистр AX: Регистры на
входе: Создать дескриптор в таблице LDT С помощью этой функции программа может создать один или несколько дескрипторов в LDT, принадлежащей задаче, в рамках которой работает программа, т.е. для своей задачи. Вся работа по инициализации полученных дескрипторов должна выполняться самой программой, для чего в интерфейсе DPMI имеются соответствующие функции. Регистры на
входе: Если программа заказывала несколько селекторов, AX содержит первый селектор из созданного массива. Для получения остальных селекторов необходимо воспользоваться функцией 00003h. Освободить дескриптор в таблице LDT Функция используется для освобождения дескрипторов, созданных в LDT предыдущей функцией. Регистры на
входе Для освобождения массива дескрипторов функцию необходимо вызывать отдельно для каждого дескриптора. Преобразование сегмента в дескриптор Функция используется для преобразования сегментной компоненты адреса реального режима в дескриптор. Регистры на
входе Дескриптор, созданный данной функцией, не может быть освобождён, поэтому эту функцию имеет смысл использовать для адресации таких областей памяти, которые будут нужны на всём протяжении работы программы (область данных BIOS, память видеоконтроллера и т.д.). Получить значение инкремента для вычисления следующего селектора в массиве Если вы создали несколько дескрипторов в LDT при помощи функции 0000h, то этой функцией будет возвращён только первый селектор, соответствующий первому дескриптору в созданном массиве. Для вычисления остальных селекторов ваша программа должна использовать функцию 0003h. Эта функция возвращает значение, которое вы будете прибавлять к базовому селектору для вычисления остальных селекторов в массиве. Регистры на
входе Зарезервированные функции Функции 0004h и 0005h в спецификации DPMI версии 0.9 зарезервированы и не должны вызываться из вашей программы. Получить базовый адрес сегмента С помощью этой функции ваша программа может определить 32-разрядный базовый адрес сегмента по его селектору. Регистры на
входе Установить базовый адрес сегмента Эта функция устанавливает базовый адрес сегмента в дескрипторе, соответствующем заданному селектору. Вы можете модифицировать только те дескрипторы, которые создала ваша программа. Регистры на
входе Установить предел сегмента Эта функция устанавливает предел сегмента в дескрипторе, соответствующем заданному селектору. Регистры на
входе Установить поле прав доступа в дескрипторе При помощи этой функции вы можете модифицироать поле прав доступа в дескрипторе, созданного вашей программой. Регистры на
входе В расширении байта прав доступа старший бит (бит 7) - бит гранулярности, который определяет интерпретацию поля предела (0 - предел в байтах, 1 - предел в страницах). Бит 6 указывает режим работы процессора (0 - 16-разрядный, 1 - 32-разрядный). Бит 5 и 2-3 должны быть равны 0. Бит 4 может содержать любое значение. Создание алиасного дескриптора для сегмента кода Так как в защищённом режиме модификация сегмента кода с использованием селектора CS невозможна, для решения такой задачи необходимо создать дескриптор сегмента данных, который бы указывал на сегмент кода (т.е. имел бы такой же базовый адрес и предел). Такой дескриптор является алиасом дескриптору сегмента кода и может быть создан при помощи функции 000Ah. Если алиас больше не нужен, он может быть уничтожен при помощи функции 0001h. Регистры на
входе Получить дескриптор С помощью этой функции программа может скопировать в буфер размером 8 байт дескриптор, соответствующий заданному селектору. Регистры на
входе Установить дескриптор Функция выполняет действия, обратные предыдущей - копирует содержимое 8-байтового буфера в дескриптор, заданный селектором. Регистры на
входе Программа может модифицировать только дескрипторы из своей локальной таблицы LDT, созданные там с помощью функции 0000h. Получить конкретный дескриптор в таблице LDT Функция позволяет получить дескриптор по его селектору. Регистры на
входе Для этой функции сервер DPMI резервирует первые 16 дескрипторов в таблице LDT. Программа может освободить полученные с помощью этой функции дескрипторв при помощи функции 0001h. Получить блок памяти из пула свободной памяти DOS С помощью этой функции программа может получить от DOS блок памяти, лежащий в пределах первого мегабайта адресного пространства. Для полученного блока памяти функция создаёт один или несколько дескрипторов (в зависимости от размера блока) и возвращает как сегмент блока для реального режима, так и базовый селектор для доступа к блоку в защищённом режиме. Если размер запрошенного блока превышает 64 килобайта, функция создаст массив дескрипторов и возвратит базовый селектор. Для получения остальных селекторов вы сможете использовать значение инкремента, полученное после вызова функции 0003h. Дескрипторы, созданные этой функцией, можно освобождать только с помощью функции 0101h. Регистры на
входе Освободить блок памяти, взятый из пула DOS Функция предназначена для освобождения памяти, полученной при помощи предыдущей функции. Регистры на
входе Изменить размер блока памяти, полученного из пула DOS С помощью этой функции программа может увеличить или уменьшить размер блока памяти, полученного функцией 0100h. Регистры на
входе Получить вектор прерывания реального режима Функция возвращает для заданного вектора прерывания адрес его обработчика в формате реального ржима. Регистры на
входе Установить вектор прерывания реального режима Функция позволяет задать для любого вектора прерывания адрес обработчика в формате реального режима. Регистры на
входе Получить адрес обработчика исключения с заданным номером Функция возвращает адрес текущего обработчика исключения с заданным номером в формате защищённого режима. Регистры на
входе Установить адрес обработчика исключения с заданным номером Функция может быть использована для установки собственного обработчика исключений. Регистры на
входе Получить вектор прерывания защищённого режима Функция возвращает адрес обработчика заданного прерывания в формате защищённого режима. Регистры на
входе Установить вектор прерывания защищённого режима С помощью этой функции программа может установить собственный обработчик защищённого режима для любого прерывания. Регистры на
входе Эмуляция прерывания реального режима Эта функция предназначена для эмуляции выполнения прерывания в реальном режиме. С её помощью вы сможете находясь в защищённом режиме обращаться к функциям BIOS, DOS и к другим прерываниям реального режима. Регистры на
входе Управляющая
структура содержит значения для
инициализации регистров перед вызовом
эмулируемого прерывания реального режима.
Она имеет следующий формат:
push Parametr1 Обработчик прерывания реального режима получит стек, подготовленный следующим образом: Parametr1 Указатель стека реального режима SS:SP установлен на слово, содержащее IP для возврата. Вызов процедуры реального режима, заканчивающейся командой RET FAR Эта процедура позволяет выполнить вызов процедуры, предназначенной для работы в реальном режиме и возвращающей управление при помощи команды RET FAR. Регистры на
входе Вызов процедуры реального режима, заканчивающейся командой IRET Эта процедура позволяет выполнить вызов процедуры, предназначенной для работы в реальном режиме и возвращающей управление при помощи команды IRET. Регистры на
входе Перехват передачи управления программе реального режима Эта функция может быть использована для перехвата передачи управления процедуре реального режима. Например, драйвер мыши выполняет вызов процедуры реального режима при перемещении мыши. Программа может сама задавать адрес реальной процедуры, которая будет получать управление при перемещении мыши или при нажатии на её кнопки. С помощью данной функции программы защищённого режима могут перехватить передачу управления этой процедуры и заменить её на другую процедуру, работающую в защищённом режиме. Регистры на
входе Процедура
защищённого режима, перехватывающая
управление, вызывается с запрещёнными
прерываниями и получает следующие
параметры:
Для выполнения возврата из процедуры перехвата необходимо выполнить команду IRET, предварительно загрузив регистры следующим образом:
Отмена перехвата передачи управления процедуре реального режима. Эта функция отменяет действие предыдущей. Регистры на
входе Получить адреса процедур сохранения/восстановления состояния. С помощью этой функции программа может сохранять или восстанавливать состояние задачи (в том числе содержимое всех регистров процессора). это бывает необходимо перед изменением реального режима работы на защищённый и обратно. Регистры на
входе Процедура сохранения/восстановления состояния вызывается командой CALL FAR и получает следующие параметры: ES:(E)DI
Указатель на буфер сохранения состояния. Получить адрес процедуры переключения режима С помощью этой функции программа может получить адреса процедур для переключения из реального режима в защищённый и из защищённого в реальный. Регистры на
входе Перед
переключением режима, которое выполняется
командой JMP FAR, необходимо подготовить
регистры:
В процессе переключения режима содержимое регистра (E)BP останется неизменным, поэтому этот регистр можно использовать как указатель. Для процессоров i80386 и i80486 после переключения режима в регситры FS и GS бует записано нулевое значение. Получить версию спецификации DPMI Функция позволяет получить текущую версию DPMI. Регистры на
входе Получить информацию о свободной памяти Регистры на
входе Формат буфера: Таблица 12. Формат буфера
для информации о свободной памяти,
получаемой средствами DPMI.
Если текущая реализация DPMI не поддерживает виртуальную память, данная функция заполняет только первое поле структуры. Остальные поля устанавливаются в -1 (0FFFFFFFFh). Получить блок памяти Эта функция предназначена для получения программой участка линейной памяти. Для полученного блока памяти не выполняется автоматического создания селектора, программа должна создать селектор самостоятельно. Регистры на
входе Освободить блок памяти Функция освобождает блок памяти, полученный при помощи предыдущей функции. Регистры на
входе Изменить размер блока памяти Функция изменяет размер блока памяти, полученного при помощи функции 0501h. Регистры на
входе Зафиксировать линейную область памяти Эта функция фиксирует в памяти область, задаваемую линейным адресом. Для зафиксированной области памяти не выполняется свопинг страниц. Регистры на
входе Расфиксирование блока памяти Эта функция должна быть использована для расфиксирования блока памяти, зафиксированного предыдущей функцией. Регистры на
входе Отмена фиксации страниц для области памяти виртуального режима Область памяти, используемая виртуальной машиной, обычно зафиксирована и не подвергается свопингу. С помощью этой функции вы можете разрешить свопинг для заданного участка памяти, принадлежащей виртуальной машине. Регистры на
входе Фиксация страниц для области памяти виртуального режима Функция предназначена для отмены действия предыдущей функции. Она фиксирует участок памяти виртуальной машины, отменяя для него свопинг страниц. Регистры на
входе Получить размер страницы памяти Функция возвращает размер страницы памяти в байтах. Регистры на
входе Зарезервированные функции Функции 0700h и 0701h зарезервированы и не должны вызываться вашей программой. Отметка страницы для свопинга Функция используется для того, чтобы сообщить операционной системе о возможности выгрузки (свопинга) на диск указанной страницы или диапазона страниц. Регистры на
входе Отвергнуть содержимое страниц Функция отмечает страницы как не содержащие полезной информации. Операционная система может использовать данные страницы для удовлетворения запросов на память. Регистры на
входе Преобразование физического адреса в линейный Функция может быть использована для работы с периферийными устройствами, адресное пространство ввода/вывода которых отображается в диапазон физических адресов. Регистры на
входе Запретить виртуальные прерывания Функция сбрасывает флаг виртуального прерывания и возвращает предыдущее состояние этого флага. Регистры на
входе Разрешить виртуальные прерывания. Функция устанавливает флаг виртуальных прерываний, разрешая виртуальные прерывания, и возвращает предыдущее состояние этого флага. Регистры на
входе Получить состояние флага виртуальных прерываний Функция позволяет узнать текущее состояние флага виртуальных прерываний. Регистры на
входе Получить адрес для использования расширений DPMI DOS-экстендеры могут расширять сервис DPMI своими функциями. Для получения доступа к этим функциям можно использовать функцию 0A00h. Вызывающая программа должна задать в регистрах DS:(E)SI адрес строки, закрытой нулём. Строка должна содержать название производителя DOS-экстендера или другой уникальный идентификатор расширения. Регистры на
входе Содержимое регистров DS, FS, GS, EAX, EBX, ECX, EDX, ESI, и EBP не сохраняется. Установить точку останова для отладки Функция позволяет установить отладочную точку останова по заданному линейному адресу. Регистры на
входе Отмена отладочной точки останова Функция отменяет точку останова, установленную при помощи предыдущей функции. Регистры на
входе Получить состояние отладочной точки останова Функция возвращает состояние отладочной точки останова, определённой при помощи функции 0B00h. Регистры на
входе Сброс точки останова Функция сбрасывает состояние для заданной отладочной точки останова. Регистры на
входе
|
Дизайн: Piton Alien |