Аппаратное обеспечение IBM PC© Александр Фролов, Григорий ФроловТом 2, книга 1, М.: Диалог-МИФИ, 1992. 10.3. Спецификация XMSСпецификация XMS содержит описание программного интерфейса драйвера HIMEM.SYS и рекомендации по использованию области памяти HMA. 10.3.1. Проверка подключения драйвераПервое, что должна сделать программа, которая собирается вызывать драйвер HIMEM.SYS - проверить, был ли установлен этот драйвер при загрузке операционной системы. Для этого надо загрузить в регистр AX значение 4300h и вызвать прерывание INT 2Fh. Если после этого регистр AL будет содержать значение 80h, драйвер установлен, в противном случае - нет. Приведем фрагмент программы, проверяющей подключение драйвера: ; Проверяем, установлен ли драйвер HIMEM.SYS mov ax, 4300h int 2fh cmp al, 80h je HMM_installed ; Выполняем переход, ; если драйвер установлен 10.3.2. Получение адреса управляющей программыДля вызова драйвера программа должна получить адрес специальной управляющей программы, которая выполняет все функции по обслуживанию расширенной памяти и области 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 байтов. 10.3.3. Описание функций драйвера HIMEM.SYSВсе функции драйвера HIMEM.SYS могут быть разделены на следующие пять групп:
Приведем подробное описание этих функций в соответствии со спецификацией XMS версии 2.0. Получить версию XMSНа входе: AH = 00h. На выходе: AX = номер версии XMS; BX = номер внутренней модификации драйвера; DX = 0001h - если существует область HMA, 0000h - если область HMA не существует. Ошибки: нет. Функция возвращает номера версии и модификации XMS в двоично-десятичном (BCD) формате. Например, если AX=0250h, это означает, что драйвер реализует спецификацию XMS версии 2.50. Дополнительно функция позволяет проверить наличие в системе области HMA. Запросить область HMAНа входе: AH = 01h; DX = размер памяти в байтах в области HMA, которая будет использоваться резидентными программами или драйверами, обычная программа должна использовать значение DX=FFFFh. На выходе: 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 = 16-битовый индекс (handle) полученного блока 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 = 16-битовый индекс (handle) блокируемого EMB. На выходе: AX = 0001h - если функция выполнена успешно 0000h - если произошла ошибка; DX:BX = 32-битовый линейный адрес заблокированного EMB. Ошибки: BL = 80h, 81h, A2h, ACh, ADh. Функция блокирует EMB и возвращает его базовый адрес как линейный 32-разрядный адрес. Для заблокированного EMB невозможно выполнить операцию копирования. Полученный линейный адрес действителен только для заблокированного EMB. Разблокирование EMBНа входе: AH = 0Dh; DX = 16-битовый индекс (handle) разблокируемого EMB. На выходе: AX = 0001h - если функция выполнена успешно 0000h - если произошла ошибка. Ошибки: BL = 80h, 81h, A2h, AAh. Функция разблокирует EMB, заблокированный при вызове предыдущей функции. Полученный от нее линейный адрес становится недействительным. Получить информацию об индексе EMBНа входе: AH = 0Eh; DX = 16-битовый индекс (handle) EMB. На выходе: AX = 0001h - если функция выполнена успешно 0000h - если произошла ошибка; BH = содержимое счетчика блокировок EMB; BL = количество свободных индексов EMB в системе; DX = размер блока в килобайтах. Ошибки: BL = 80h, 81h, A2h. Эта функция используется для получения различной информации об используемых блоках EMB. Линейный адрес блока может быть получен с помощью фунции 0Ch. Изменить размер EMBНа входе: AH = 0Fh; DX = 16-битовый индекс (handle) незаблокированного 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=FFFFh. Освободить область UMBНа входе: AH = 11h; DX = сегмент освобождаемого UMB. На выходе: AX = 0001h - если функция выполнена успешно 0000h - если произошла ошибка. Ошибки: BL = 80h, B2h. После освобождения блока EMB данные, которые там находились, будут потеряны. 10.3.4. Коды ошибокПриведем таблицу кодов ошибок, возвращаемых
функциями в регистре BL:
|