Интерфейс XMS
Спецификация доступа к дополнительной памяти (XMS) — еще один метод, позволяющий программам, запускающимся под управлением DOS в реальном режиме (или в режиме V86), использовать память, расположенную выше границы первого мегабайта.
INT 2Fh, АН = 43 — XMS- и DPMS-сервисы
Ввод: |
АХ = 4300h: проверить наличие XMS |
Вывод: |
АН = 80h, если HIMEM.SYS или совместимый драйвер загружен |
Ввод: |
АХ = 4310h: получить точку входа XMS |
Вывод: |
ES:BX = дальний адрес точки входа XMS |
После определения точки входа все функции XMS вызываются с помощью команды CALL на указанный дальний адрес.
Функция XMS 00h — Определить номер версии
Ввод: |
AH = 00h |
Вывод: |
АХ = номер версии, не упакованный BCD (0300h для 3.0) ВХ = внутренний номер модификации DX = 1, если HMA существует, 0, если нет |
Функция XMS 08h — Определить объем памяти
Ввод: |
АН = 08h BL = 00h |
Вывод: |
АХ = размер максимального доступного блока в килобайтах DX = размер всей XMS-памяти в килобайтах BL = код ошибки (A0h, если вся XMS-память занята, 00, если нет ошибок) |
Так как возвращаемый размер памяти оказывается ограниченным размером слова (65 535 Кб), начиная с версии XMS 3.0, введена более точная функция 88h.
Функция XMS 88h — Определить объем памяти
Ввод: |
AH = 88h |
Вывод: |
ЕАХ = размер максимального доступного блока в килобайтах BL = код ошибки (A0h, если вся XMS-память занята, 00 — если нет ошибок) ЕСХ = физический адрес последнего байта памяти (верный для ошибки А0h) EDX = размер XMS-памяти всего в килобайтах (0 для ошибки А0h) |
Функция XMS 09h — Выделить память
Ввод: |
АН = 09h DX = размер запрашиваемого блока (в килобайтах) |
Вывод: |
АХ = 1, если функция выполнена ВХ = идентификатор блока АХ = 0: BL = код ошибки (A0h, если не хватило памяти) |
Функция XMS 0Ah — Освободить память
Ввод: |
АН = 0Ah DX = идентификатор блока |
Вывод: |
АХ = 1, если функция выполнена Иначе — АХ = 0 и BL = код ошибки (A2h — неправильный идентификатор, ABh — участок заблокирован) |
<
/p>
Функция XMS 0Bh — Пересылка данных
Ввод: |
АН = 0Bh DS:SI = адрес структуры для пересылки памяти |
Вывод: |
АХ = 1, если функция выполнена Иначе — АХ = 0 и BL = код ошибки |
Структура данных, адрес которой передается в DS:SI:
+00h: 4 байта — число байт для пересылки
+04h: слово — идентификатор источника (0 для обычной памяти)
+06h: 4 байта — смещение в блоке-источнике или адрес в памяти
+0Ah: слово — идентификатор приемника (0 для обычной памяти)
+0Ch: 4 байта — смещение в блоке-приемнике или адрес в памяти
Адреса в обычной памяти записываются в соответствующие двойные слова в обычном виде — сегмент:смещение. Копирование происходит быстрее, если данные выровнены на границы слова или двойного слова; если области данных перекрываются, адрес начала источника должен быть меньше адреса начала приемника.
Функция XMS 0Fh — Изменить размер XMS-блока
Ввод: |
АН = 0Fh ВХ = новый размер DX = идентификатор блока |
Вывод: |
АХ = 1, если функция выполнена Иначе — АХ = 0 и BL = код ошибки |
Кроме того, XMS позволяет программам использовать область НМА и блоки UMB, если они не заняты DOS при запуске (так как в CONFIG.SYS не было строк DOS = HIGH или DOS = UMB).
; mem.asm ; сообщает размер памяти, доступной через EMS и XMS ; .model tiny .code .186 ; для команд сдвига на 4 org 100h ; СОМ-программа start: cld ; команды строковой обработки ; будут выполняться вперед
; проверка наличия EMS
mov dx,offset ems_driver ; адрес ASCIZ-строки "EMMXXXX0" mov ax,3D00h int 21h ; открыть файл или устройство jc no_emmx ; если не удалось открыть - EMS нет mov bx,ax ; идентификатор в ВХ mov ax,4400h int 21h ; IOCTL: проверить состояние файла/устройства jc no_ems ; если не произошла ошибка, test dx,80h ; проверить старший бит DX, jz no_ems ; если он - 0, EMMXXXXO - файл в текущем ; каталоге
; определение версии EMS
mov ah,46h int 67h ; получить версию EMS test ah,ah jnz no_ems ; если EMS выдал ошибку - не стоит продолжать ; с ним работать mov ah,al and al,0Fh ; AL = старшая цифра shr ah,4 ; AH = младшая цифра call output_version ; выдать строку о номере версии EMS
; определение доступной EMS-памяти
mov ah,42h int 67h ; получить размер памяти ; в 16-килобайтных страницах shl dx,4 ; DX = размер памяти в килобайтах shl bx,4 ; ВХ = размер свободной памяти в килобайтах mov ax,bx mov si,offset ems_freemem ; адрес строки для output_info call output_info ; выдать строки о размерах памяти
no_ems: mov ah,3Eh int 21h ; закрыть файл/устройство EMMXXXX0 no_emmx:
; проверка наличия XMS
mov ax,4300h int 2Fh ; проверка XMS, cmp al,80h ; если AL не равен 80h, jne no_xms ; XMS отсутствует, mov ax,4310h ; иначе: int 2Fh ; получить точку входа XMS mov word ptr entry_pt,bx ; и сохранить ее в entry_pt mov word ptr entry_pt+2,es ; (старшее слово - по старшему адресу!) push ds pop es ; восстановить ES
; определение версии XMS
mov ah,00 call dword ptr entry_pt ; Функция XMS 00h - номер версии mov byte ptr mem_version,'X' ; изменить первую букву строки ; "EMS версии" на "X" call output_version ; выдать строку о номере версии XMS
; определение доступной XMS-памяти
mov ah,08h xor bx,bx call dword ptr entry_pt ; Функция XMS 08h mov byte ptr totalmem,'X' ; изменить первую букву строки ; "EMS-памяти" на "X" mov si,offset xms_freemem ; строка для output_info
; вывод сообщений на экран: ; DX - объем всей памяти ; АХ - объем свободной памяти ; SI - адрес строки с сообщением о свободной памяти (разный для EMS и XMS)
output_info: push ax mov ax,dx ; объем всей памяти в АХ mov bp,offset totalmem ; адрес строки - в ВР call output_info1 ; вывод pop ах ; объем свободной памяти - в АХ mov bp,si ; адрес строки - в ВР
output_info1: ; вывод mov di,offset hex2dec_word
; hex2dec ; преобразует целое двоичное число в АХ ; в строку десятичных ASCII-цифр в ES:DI, заканчивающуюся символом "$" mov bx,10 ; делитель в ВХ xor сх,сх ; счетчик цифр в 0 divlp: xor dx,dx div bx ; разделить преобразуемое число на 10 add dl,'0' ; добавить к остатку ASCII-код нуля push dx ; записать полученную цифру в стек inc cx ; увеличить счетчик цифр test ax,ax ; и, если еще есть, что делить, jnz divlp ; продолжить деление на 10 store: pop ax ; считать цифру из стека stosb ; дописать ее в конец строки в ES:DI loop store ; продолжить для всех СХ-цифр mov byte ptr es:[di],'$' ; дописать '$' в конец строки mov dx,bp ; DX - адрес первой части строки mov ah,9 int 21h ; Функция DOS 09h - вывод строки mov dx,offset hex2dec_word ; DX - адрес строки с десятичным числом int 21h ; вывод строки mov dx,offset eol ; DX - адрес последней части строки int 21h ; вывод строки
no_xms: ret ; конец программы и процедур ; output_info и output_info1
; вывод версии EMS/XMS ; АХ - номер в неупакованном BCD-формате
output_version: or ax,3030h ; преобразование неупакованного BCD в ASCII mov byte ptr major,ah ; старшая цифра в major mov byte ptr minor,al ; младшая цифра в minor mov dx,offset mem_version ; адрес начала строки - в DX mov ah,9 int 21h ; вывод строки ret
ems_driver db "EMMXXXX0",0 ; имя драйвера для проверки EMS mem_version db "EMS версии " ; сообщение о номере версии major db "0." ; первые байты этой minor db "0 обнаружен ",0Dh,0Ah,"$" ; и этой строк будут ; заменены реальными номерами версий totalmem db "EMS-памяти: $" ems_freemem db "EMS-памяти: $" eol db "K",0Dh,0Ah,'$' ; конец строки xms_freemem db "Наибольший свободный блок XMS: $"
entry_pt: ; сюда записывается точка входа XMS hex2dec_word equ entry_pt+4 ; буфер для десятичной строки end start
Содержание раздела