[Назад] [Далее]

4.9.5. Интерфейс 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 — участок заблокирован)

Функция XMS 0Bh — Пересылка данных

Ввод: АН = 0Bh
DS:SI = адрес структуры для пересылки памяти
Вывод: АХ = 1, если функция выполнена
Иначе — АХ = 0 и BL = код ошибки

Структура данных, адрес которой передается в DS:SI:

Адреса в обычной памяти записываются в соответствующие двойные слова в обычном виде — сегмент:смещение. Копирование происходит быстрее, если данные выровнены на границы слова или двойного слова; если области данных перекрываются, адрес начала источника должен быть меньше адреса начала приемника.


Функция 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

п»ї
"target=_blank><\/a>") //-->