Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Аппаратное обеспечение персонального компьютера

© Александр Фролов, Григорий Фролов
Том 33, М.: Диалог-МИФИ, 1997, 304 стр.

[Назад] [Содеожание] [Дальше]

Спецификация XMS

Спецификация XMS содержит описание программного интерфейса драйвера HIMEM.SYS и рекомендации по использованию области памяти HMA.

Проверка подключения драйвера

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

Для этого надо загрузить в регистр AX значение 4300h и вызвать прерывание INT 2Fh. Если после этого регистр AL будет содержать значение 80h, драйвер установлен, в противном случае - нет.

Приведем фрагмент программы, проверяющей подключение драйвера:


	; Проверяем, установлен ли драйвер HIMEM.SYS
	  mov   ax, 4300h
	  int   2fh
	  cmp   al, 80h
	
	; Если драйвер установлен, выполняем переход
	  je    HMM_installed

Получение адреса управляющей программы

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

Этот адрес можно получить, если загрузить в регистр AX значение 4310h и вызвать прерывание INT 2Fh. Прерывание возвратит сегментный адрес управляющей программы в регистре ES, смещение - в регистре BX:


	; Получаем адрес управляющей функции драйвера
	  mov   ax, 4310h
	  int   2fh
	  mov   word ptr cs:[HMMEntry][0], bx
	  mov   word ptr cs:[HMMEntry][2], es

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


	; Получаем номер версии драйвера HIMEM.SYS
	  mov   ax,0
	  call  [HMMEntry]

Программы, которые обращаются к управляющей функции, должны перед вызовом функции иметь размер стека не менее 256 байт.

Описание функций драйвера HIMEM.SYS

Все функции драйвера HIMEM.SYS могут быть разделены на следующие пять групп:

·          функции получения информации о драйвере (0h);

·          функции управления областью HMA (1h...2h);

·          функции управления линией A20 (3h...7h);

·          функции управления расширенной памятью (8h...Fh);

·          функции управления блоками UMB (10h...11h).

Приведем подробное описание этих функций в соответствии со спецификацией XMS версии 2.0.

Получить версию XMS

Регистры на входе:

AH = 00h

Регистры на выходе:

BX = номер внутренней модификации драйвера;

DX = 0001h - если существует область HMA,

DX = 0000h - если область HMA не существует

Функция возвращает номера версии и модификации XMS в двоично-десятичном (BCD) формате. Например, если AX=0250h, это означает, что драйвер соответствует спецификации XMS версии 2.50. Дополнительно функция позволяет проверить наличие в системе области HMA.

Запросить область HMA

Регистры на входе:

AH = 01h

DX = размер памяти в байтах в области HMA, которая будет использоваться резидентными программами или драйверами. Обычная программа должна указывать значение DX, равное 0FFFFh

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, 90h, 91h, 92h (описание кодов ошибок будет приведено после описания всех функций)

С помощью этой функции программа может зарезервировать для себя область HMA. Задаваемый в регистре DX размер памяти сравнивается с указанным в параметре драйвера /HMAMIN=. Область HMA распределяется запросившей программе только в том случае, если запрошенный в регистре DX размер больше или равен указанному в параметре /HMAMIN. Такой механизм позволяет ограничить использование области HMA только теми программами, которые используют ее наилучшим образом.

Поясним это на примере. Пусть при инициализации операционной системы из файла AUTOEXEC.BAT запускаются две программы. Одна из них использует 10 Кбайт из области HMA и запускается первой (в регистре DX функции 01h эта программа указывает значение 10240). Вторая запускаемая программа использует 40 Кбайт и запускается после первой. Очевидно, что вторая программа использует область HMA более эффективно. Но так как область HMA уже распределена первой программе, вторая программа не сможет получить ее для себя.

Задавая параметр /HMAMIN =40, мы запретим распределение области HMA тем программам, которые используют в ней меньше 40 Кбайт. Теперь первая программа не получит доступ к области HMA, даже если она будет запускаться до второй, использующей 40 Кбайт памяти из области HMA.

Освободить область HMA

Регистры на входе:

AH = 02h

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, 90h, 93h

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

После того, как программа освободила область HMA, эта область становится доступной другим программам.

Глобальное открывание линии A20

Регистры на входе:

AH = 03h

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, 82h

Эта функция предназначена для тех программ, которые будут использовать область HMA. Она разрешает работу заблокированной по умолчанию 21 адресной линии процессора. Перед возвратом управления системе программа должна закрыть линию A20 с помощью функции 04h.

Следует отметить, что для многих типов системных плат переключение линии A20 - достаточно медленная операция.

Глобальное закрывание линии A20

Регистры на входе:

AH = 04h

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, 82h, 94h

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

Локальное открывание линии A20

Регистры на входе:

AH = 05h

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, 82h

Эта функция предназначена только для тех программ, которые непосредственно управляют расширенной памятью. Перед завершением работы программа должна закрыть линию A20 при помощи функции 06h.

Локальное закрывание линии A20

Регистры на входе:

AH = 06h

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, 82h, 94h

Функция отменяет разрешение линии A20, запрошенное предыдущей функцией. Она предназначена только для тех программ, которые непосредственно управляют расширенной памятью.

Определение состояния линии A20

Регистры на входе:

AH = 07h

Регистры на выходе:

AX = 0001h - если линия A20 открыта, 0000h - если линия A20 закрыта

Ошибки:

BL = 00h, 80h, 81h

Функция выполняет попытку адресоваться за границу 1 Мбайт памяти и проверяет, не происходит ли при этом обращение в начало памяти (то есть "свертка памяти").

Определение размера свободной расширенной памяти

Регистры на входе:

AH = 08h

Регистры на выходе:

AX = размер наибольшего свободного блока расширенной памяти, Кбайт;

DX = общий размер свободной расширенной памяти, Кбайт

Ошибки:

BL = 80h, 81h, A0h

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

Получить блок EMB

Регистры на входе:

AH = 09h

DX = размер требуемого блока, Кбайт

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка;

DX = 16-разрядный идентификатор (handle) полученного блока EMB

Ошибки:

BL = 80h, 81h, A0h, A1h

Функция заказывает блок EMB из пула свободной расширенной памяти. При успешном выполнении запроса функция возвращает идентификатор полученного блока, который должен использоваться программой для выполнения всех операций с блоком EMB. Если блок EMB программе больше не нужен, она должна освободить его с помощью функции 0Ah.

Количество блоков EMB, которое может быть заказано, определяется в командной строке драйвера HIMEM.SYS параметром /NUMHANDLES=. Значение по умолчанию - 32, максимальное значение - 128.

Освободить блок EMB

Регистры на входе:

AH = 0Ah

DX = идентификатор освобождаемого блока EMB

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, A2h, B2h

Функция освобождает блок EMB, заказанный предыдущей функцией. При этом все данные, находившиеся в блоке, будут потеряны.

Копирование блоков EMB

Регистры на входе:

AH = 0Bh

DS:SI = указатель на управляющую структуру, определяющую откуда, куда и как будет выполняться копирование

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, 82h, A3h, A4h, A5h, A6h, A7h, A8h, A9h

Формат управляющей структуры представлен ниже:


	ExtMemMoveStruct  struc
	  Length         dd ?    ; количество пересылаемых байт
	  SourceHandle   dw ?    ; индекс исходного блока
	  SourceOffset   dd ?    ; смещение в исходном блоке
	  DestHandle     dw ?    ; индекс блока-назначения
	  DestOffset     dd ?    ; смещение в блоке-назначении
	ExtMemMoveStruct  ends

Эта функция выполняет основную операцию с блоками EMB - копирование данных. Данные могут пересылаться между обычной памятью и блоками EMB, между различными блоками EMB и даже внутри обычной памяти.

Поле Length управляющей структуры указывает количество пересылаемых байт данных. Это количество должно быть четным.

Поля SourceHandle и DestHandle указывают, соответственно, идентификаторы исходного блока EMB и блока, в который выполняется копирование. Если в качестве идентификатора задано значение 0000h, это означает, что в качестве источника или приемника данных используется обычная память.

Поля SourceOffset и DestOffset указывают 32-разрядное смещение в блоке EMB или адрес в обычной памяти. В последнем случае этот адрес имеет стандартный формат [сегмент:смещение].

Функция копирования сама управляет линией A20, восстанавливая ее состояние после выполнения копирования. Поэтому программе не требуется управлять линией A20.

Во время выполнения копирования разрешены прерывания.

Блокирование EMB

Регистры на входе:

AH = 0Ch

DX = идентификатор блока EMB

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка;

DX:BX = 32-разрядный линейный адрес заблокированного EMB

Ошибки:

BL = 80h, 81h, A2h, ACh, ADh

Функция блокирует EMB и возвращает его базовый адрес как линейный 32-разрядный адрес. Для заблокированного EMB невозможно выполнить операцию копирования. Полученный линейный адрес действителен только для заблокированного EMB.

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

Регистры на входе:

AH = 0Dh

DX = идентификатор блока EMB

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, A2h, AAh

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

Получить информацию об идентификаторе блока EMB

Регистры на входе:

AH = 0Eh

DX = идентификатор блока EMB

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка;

BH = содержимое счетчика блокировок EMB;

BL = количество свободных идентификаторов блоков EMB в системе;

DX = размер блока, Кбайт

Ошибки:

BL = 80h, 81h, A2h

Эта функция используется для получения различной информации об используемых блоках EMB. Линейный адрес блока может быть получен с помощью фунции 0Ch.

Изменить размер EMB

Регистры на входе:

AH = 0Fh

DX = идентификатор блока EMB;

BX = новый размер EMB, Кбайт

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, 81h, A0h, A1h, A2h, ABh

Функция изменяет размер незаблокированного EMB. Если размер блока уменьшается, данные в старших адресах блока будут потеряны.

Запросить область UMB

Регистры на входе:

AH = 10h

DX = размер запрашиваемого блока UMB в параграфах

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка;

BX = сегмент полученного UMB;

DX = размер полученного блока или размер максимального свободного блока UMB (если невозможно выделить блок требуемого размера)

Ошибки:

BL = 80h, B0h, B1h

Эта функция позволяет программе получить дступ к блокам UMB, лежащих в пределах первого мегабайта адресного пространства. Для использования этих блоков не требуется управлять линией A20.

Если вам надо определить размер доступной области UMB, задайте при вызове этой функции DX=0FFFFh.

Освободить область UMB

Регистры на входе:

AH = 11h

DX = сегмент освобождаемого UMB

Регистры на выходе:

AX = 0001h - если функция выполнена успешно, 0000h - если произошла ошибка

Ошибки:

BL = 80h, B2h

После освобождения блока EMB данные, которые там находились, будут потеряны.

Коды ошибок

Приведем таблицу кодов ошибок, возвращаемых функциями в регистре BL:

PRIVATEКод

Ошибка

00h

Нет ошибки, нормальное завершение

80h

Функция не реализована в текущей версии драйвера

81h

Обнаружен драйвер VDISK.SYS, с этим драйвером драйвер HIMEM.SYS несовместим

82h

Ошибка при работе с линией A20

8Eh

Общая ошибка драйвера

8Fh

Катастрофическая ошибка драйвера

90h

Область HMA не существует

91h

Область HMA уже используется

92h

Содержимое регитра DX меньше парметра /HMAMIN=

93h

Область HMA не распределена программе

94h

Линия A20 все еще разблокирована

A0h

Вся расширенная память уже распределена

A1h

Больше нет свободных индексов EMB

A2h

Неправильный индекс EMB

A3h

Неправильный SourceHandle

A4h

Неправильный SourceOffset

A5h

Неправильный DestHandle

A6h

Неправильный DestOffset

A7h

Неправильный Length

A8h

Неразрешенное перекрытие данных при выполнении операции пересылки данных

A9h

Произошла ошибка четности

AAh

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

ABh

EMB заблокирован

ACh

Переполнение счетчика блокировок EMB

ADh

Не удалось выполнить блокировку EMB

B0h

Доступен UMB меньшего размера

B1h

Нет доступных блоков UMB

B2h

Задан неправильный сегмент UMB


[Назад] [Содеожание] [Дальше]