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

Аппаратное обеспечение 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 могут быть разделены на следующие пять групп:

  • функции получения информации о драйвере (0h);
  • функции управления областью HMA (1h...2h);
  • функции управления линией A20 (3h...7h);
  • функции управления расширенной памятью (8h...Fh);
  • функции управления блоками UMB (10h...11h).

Приведем подробное описание этих функций в соответствии со спецификацией 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:

Код Ошибка
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
[Назад] [Содеожание] [Дальше]