Assembler - язык неограниченных возможностей

         

Интерфейс 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


Содержание раздела