Графические устройства



     

Использование функций драйвера

Для корректной работы с расширенной памятью задачи должны выполнять определенную последовательность действий, а именно:

  1. 1. Проверить наличие менеджера, поддерживающего функции EMS.
  2. 2. Получить код сегмента, на который отображается расширенная память.
  3. 3. Определить наличие требуемого пространства расширенной памяти.
  4. 4. Отобразить часть пространства ОЗУ на физические страницы.
  5. 5. В пределах сегмента работать с расширенной памятью как с обычной.
  6. 6. При достижении границ сегмента повторять пункты 4 и 5.
  7. 7. Перед завершением задачи вернуть память менеджеру.

Выполнение первого пункта списка является скорее данью традиции, чем необходимостью, поскольку ПК на базе Intel 386 и всех последующих моделей обязательно имеют оборудование для доступа к расширенной памяти. Для проверки можно, например, с помощью функции 40h определить статус, а с помощью функции 4бп — номер версии драйвера и убедиться, что он не меньше чем 4.0. Остальные пункты списка обязательно должны выполняться, причем в той последовательности, в которой они перечислены.

Специальные переменные

При работе с Expanded memory обязательно используются код сегмента расширенной памяти и идентификаторы выделенных блоков. В некоторых случаях могут быть нужны номера последних логических страниц в выделенных блоках и другие величины. Для их хранения в разделе данных задачи надо выделить специальные переменные, количество которых зависит от количества открытых блоков.

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

EBuff dw 0 ; код сегмента для доступа к расширенной памяти
Ehndlr dw 0 ; идентификатор блока выделенного для задачи
Curpg db 0 ; номер текущей логической страницы блока
Lastpg db 0 ; номер последней логической страницы блока

Номера текущей и последней страниц нужны при работе с большими блоками, размер которых превышает 65 536 байтов (4 страницы). При работе с ними приходится многократно отображать его логические страницы на физические. Если же размер блока не превышает стандартного сегмента ОЗУ, то он отображается на физические страницы только один раз и при дальнейшей работе номера страниц не нужны.
При работе с несколькими блоками в разделе данных задачи можно организовать простую таблицу, состоящую из строк фиксированного размера, содержащих характеристики каждого блока. В таком случае характеристики выбираются из таблицы по порядковому номеру блока, и сокращается количество имен переменных.

Резервирование блока

Предположим, что для выполнения задачи требуется непрерывное пространство расширенной памяти (блок) размером в 1 Мбайт. Для резервирования такого блока задача должна запросить у драйвера исполнение функции 43h, указав в регистре bx 64 страницы (размер страницы составляет 16 Кбайт). Если это первый запрос, обращенный к драйверу, то предварительно надо выполнить функцию 4 in для определения состояния драйвера и получения кода сегмента для доступа к памяти.

Фрагмент программы, выполняющий резервирование блока размером в 1 Мбайт, приведен в примере Б.5. Его надо включить в ту часть задачи, где выполняются подготовительные действия. Например, сразу после команд, приведенных в примерах Б.З или Б.4.

Пример Б. 5. Создание в расширенной памяти блока размером 1 Мбайт

mov ax, 4100h код функции запроса сегмента
int 67h обращение к драйверу
or ah, ah функция выполнена ?
je @F -> да
jmp emmerr -> ошибка при исполнении функции
@@: mov EBuff, bx сохраняем код сегмента
mov bx, 64 размер запрашиваемого блока
mov ax, 4300h код функции выделения памяти
int 67h обращение к драйверу
or ah, ah блок выделен ?
je @F -> да
jmp emmerr -> ошибка при выделении блока
@@: mov Ehndlr, dx сохраняем идентификатор блока
mov Curpg, 0 номер текущей страницы блока
mov Lastpg, 63 номер последней страницы блока
; Продолжение текст а программы

Выполнение примера Б.5 начинается с запроса кода сегмента для доступа к расширенной памяти. Если при возврате из драйвера регистр ah очищен, то запрос исполнен успешно, в противном случае произойдет переход на метку emmerr. для вывода аварийного сообщения.

На следующем шаге выдается запрос на выделение блока размером в 64 страницы. Если после возврата из драйвера регистр ah очищен, то блок выделен, в противном случае происходит переход на метку emmerr.

В случае успешного выделения блока формируются Curpg и Lastpg и на этом выполнение фрагмента завершено.

В примере Б.5 отсутствуют команды, обработки аварийных ситуаций. Предполагается, что первая из них имеет метку emmerr. Что делать в случае ошибки, решать вам, например, можно вывести на экран текст аварийного сообщения и завершить выполнение задачи. На стадии отладки полезно предусмотреть вывод кода ошибки, который находится в регистре ah.

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

Отображение страниц

Для отображения логической страницы блока на одну из физических страниц сегмента EMS запрашивается функция 44h. Мы рассмотрим универсальный вариант подпрограммы отображения страниц.

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

При вызове call mapseg отображаются четыре подряд расположенные страницы. Предварительно в регистре bx указывается номер первой логической страницы, а в регистре dx — идентификатор блока, которому принадлежат отображаемые страницы. Вариант вызова подпрограммы mapseg показан в примере Б.7 (см. раздел).

При вызове call mapip дополнительно (кроме заполнения регистров bx и dx) в регистре ах указывается номер первой физической страницы, а в регистре сх — количество страниц.

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

Пример Б.6. Подпрограмма отображения 4-х страниц сегмента EMS

mapseg: mov ex, 04 ; количество повторов цикла
xor al, al нулевая физическая страница
maplp : reov ah, 44h код функции отображения памяти
int 67h обращение к драйверу
or ah, ah отображение выполнено?
jne @F -> нет, переход на локальную метку
inc ax следующая физическая страница
inc bx следующая логическая страница
loop maplp управление повторами цикла
clc очистка С-разряда
ret возврат на основную программу
@@: stc установка С-разряда
ret возврат на основную программу

При входе в точку mapseg задается 4 повтора цикла отображения начиная с нулевой физической страницы. После этого выполняется цикл отображения, имеющий метку mapip (вторая точка входа).

Если отображение происходит без ошибок, то номера физической и логической страницы увеличиваются на 1 и цикл повторяется до тех пор, пока не будет отображено заданное количество страниц.

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

Освобождение памяти

Для освобождения выделенного задаче блока выполняются следующие действия:

mov dx, Ehndlr ; dx = идентификатор блока
mov ax, 4500h ; ах = код функции освобождения блока
int 67h ; обращение к драйверу

При исполнении запроса драйвер открепляет пространство блока от задачи, и оно становится общедоступным.

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

Освобождаются все блоки, затребованные задачей. Для этого описанные команды повторяются, с указанием в регистре dx идентификаторов разных блоков, закрепленных за задачей.

     
Назад Начало Вперед