; Это интерфейсный модуль для вызова функций
; XMS из Си. Текст программы рассчитан на
; модель памяти Small.

	  .model small,c
	  .DATA

; В этом месте будет храниться адрес
; управляющей функции XMM

XMM_Control  dd   ?

	  .CODE

; Макроопределения для выполнения соглашения об
; использовании регистров в процедурах Си

c_begin macro
			 push bp
			 mov  bp,sp
			 push si
			 push di
		  endm

c_end   macro
			 pop  di
			 pop  si
			 mov  sp,bp
			 pop  bp
			 ret
		  endm

; Все процедуры должны быть public

	public XMM_Installed
	public XMM_Version
	public XMM_RequestHMA
	public XMM_ReleaseHMA
	public XMM_GlobalEnableA20
	public XMM_GlobalDisableA20
	public XMM_EnableA20
	public XMM_DisableA20
	public XMM_QueryA20
	public XMM_QueryLargestFree
	public XMM_QueryTotalFree
	public XMM_AllocateExtended
	public XMM_FreeExtended
	public XMM_MoveExtended
	public XMM_LockExtended
	public XMM_UnLockExtended
	public XMM_GetHandleLength
	public XMM_GetHandleInfo
	public XMM_ReallocateExtended
	public XMM_RequestUMB
	public XMM_ReleaseUMB

;**
;.Name         XMM_Installed
;.Title        Получение адреса управляющей функции
;
;.Descr        Эта функция проверяет наличие драйвера
;              HIMEM.SYS и в случае его присуствия
;              запоминает адрес управляющей функции.
;
;.Proto        unsigned XMM_Installed(void);
;
;.Params       Не используются
;
;.Return       0 - драйвер HIMEM.SYS не установлен;
;              1 - драйвер HIMEM.SYS установлен.
;
;.Sample       xms_test.c
;**

XMM_Installed proc near
			 c_begin

			 mov  ax, 4300h
          int  2fh
          cmp  al, 80h
			 jne  NotInstalled

			 mov  ax, 4310h
          int  2fh
          mov  word ptr [XMM_Control], bx
          mov  word ptr [XMM_Control+2], es
			 mov  ax,1
			 jmp  Installed

NotInstalled:
			 mov  ax, 0
Installed:
			 c_end
XMM_Installed endp

;**
;.Name         XMM_Version
;.Title        Определение версии драйвера HIMEM.SYS
;
;.Descr        Эта функция определяет версию драйвера
;              HIMEM.SYS
;
;.Proto        long  XMM_Version(void);
;
;.Params       Не используются
;
;.Return       Номер версии в младших 16 битах,
;              номер изменений - в старших 16 битах
;              возвращаемого значения
;
;.Sample       xms_test.c
;**

XMM_Version proc near
          push si
			 push di
			 xor  ah,ah
			 call [XMM_Control]
			 mov  dx, bx
          pop  di
          pop  si
          ret
XMM_Version endp

;**
;.Name         XMM_RequestHMA
;.Title        Запросить область HMA
;
;.Descr        Эта функция пытается зарезервировать для
;              программы область HMA
;
;.Proto        long  XMM_RequestHMA(unsigned space);
;
;.Params       space - размер требуемой области для
;                      TSR-программы или драйвера,
;                      0xffff для прикладной программы;
;
;.Return       < 0 - область HMA не назначена программе,
;                    код ошибки находится в старшем байте.
;              0L  - область HMA назначена программе.
;
;.Sample       xms_test.c
;**

XMM_RequestHMA proc near
			 c_begin
			 mov  ah, 1
			 mov  dx, [bp+4]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @success
          mov  dh, bl
@success:
			 c_end
XMM_RequestHMA endp


;**
;.Name         XMM_ReleaseHMA
;.Title        Освободить область HMA
;
;.Descr        Эта функция пытается освободить
;              область HMA
;
;.Proto        long  XMM_ReleaseHMA(void);
;
;.Params       Не используются
;
;.Return       < 0 - область HMA не освобождена,
;                    код ошибки находится в старшем байте.
;              0L - область HMA освобождена.
;
;.Sample       xms_test.c
;**

XMM_ReleaseHMA proc near
			 c_begin
          mov  ah, 2
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @success1
          mov  dh, bl
@success1:
			 c_end
XMM_ReleaseHMA endp

;**
;.Name         XMM_GlobalEnableA20
;.Title        Глобальное разрешение линии A20
;
;.Descr        Эта функция разрешает программе, получившей
;              доступ к области HMA использовать линию A20
;
;.Proto        long  XMM_GlobalEnableA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - линия A20 не включена,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 включена.
;
;.Sample       xms_test.c
;**

XMM_GlobalEnableA20 proc near
			 c_begin
			 mov  ah, 3
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @success2
          mov  dh, bl
@success2:
			 c_end
XMM_GlobalEnableA20 endp

;**
;.Name         XMM_GlobalDisableA20
;.Title        Глобальное запрещение линии A20
;
;.Descr        Эта функция запрещает программе, получившей
;              доступ к области HMA использовать линию A20
;
;.Proto        long  XMM_GlobalDisableA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - линия A20 не выключена,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 выключена.
;
;.Sample       xms_test.c
;**

XMM_GlobalDisableA20 proc near
			 c_begin
			 mov  ah, 4
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @success3
          mov  dh, bl
@success3:
			 c_end
XMM_GlobalDisableA20 endp

;**
;.Name         XMM_EnableA20
;.Title        Локальное разрешение линии A20
;
;.Descr        Эта функция разрешает программе управлять
;              областью расширенной памяти.
;
;.Proto        long  XMM_EnableA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - линия A20 не включена,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 включена.
;
;.Sample       xms_test.c
;**

XMM_EnableA20 proc near
			 c_begin
          mov  ah, 5
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @success4
          mov  dh, bl
@success4:
			 c_end
XMM_EnableA20 endp

;**
;.Name         XMM_DisableA20
;.Title        Локальное запрещение линии A20
;
;.Descr        Эта функция запрещает программе управлять
;              областью расширенной памяти.
;
;.Proto        long  XMM_DisableA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - линия A20 не выключена,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 выключена.
;
;.Sample       xms_test.c
;**

XMM_DisableA20 proc near
			 c_begin
          mov  ah, 6
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @success5
          mov  dh, bl
@success5:
			 c_end
XMM_DisableA20 endp

;**
;.Name         XMM_QueryA20
;.Title        Проверить состояние линии A20
;
;.Descr        Эта функция проверяет доступность
;              линии A20
;
;.Proto        long  XMM_QueryA20(void);
;
;.Params       Не используются
;
;.Return       < 0 - ошибка,
;                    код ошибки находится в старшем байте.
;              0L  - линия A20 выключена,
;              1L  - линия A20 включена.
;
;.Sample       xms_test.c
;**

XMM_QueryA20 proc near
			 c_begin
          mov  ah, 7
          call [XMM_Control]
          xor  dx, dx
          or   ax, ax
			 jnz  @success6
          mov  dh, bl
@success6:
			 c_end
XMM_QueryA20 endp

;**
;.Name         XMM_QueryLargestFree
;.Title        Определить максимальный размер блока
;
;.Descr        Эта функция возвращает размер максимального
;              непрерывного блока расширенной памяти,
;              который доступен программе.
;
;.Proto        long  XMM_QueryLargestFree(void);
;
;.Params       Не используются
;
;.Return       < 0 - ошибка,
;                    код ошибки находится в старшем байте.
;              >= 0 - размер блока.
;
;.Sample       xms_test.c
;**

XMM_QueryLargestFree proc near
			 c_begin
          mov  ah, 8
          call [XMM_Control]
          xor  dx, dx
          or   ax, ax
			 jnz  @success7
          mov  dh, bl
@success7:
			 c_end
XMM_QueryLargestFree endp

;**
;.Name         XMM_QueryTotalFree
;.Title        Определить размер расширенной памяти
;
;.Descr        Эта функция возвращает размер
;              всей имеющейся расширенной памяти.
;
;.Proto        long  XMM_QueryTotalFree(void);
;
;.Params       Не используются
;
;.Return       < 0 - ошибка,
;                    код ошибки находится в старшем байте.
;              >= 0 - размер расширенной памяти.
;
;.Sample       xms_test.c
;**

XMM_QueryTotalFree proc near
			 c_begin
			 mov  ah, 8
          call [XMM_Control]
          or   ax, ax
          mov  ax, dx
			 mov  dx, 0
			 jnz  @success8
          mov  dh, bl
@success8:
			 c_end
XMM_QueryTotalFree endp

;**
;.Name         XMM_AllocateExtended
;.Title        Запросить блок расширенной памяти
;
;.Descr        Эта функция выделяет программе блок
;              расширенной памяти, в случае успеха
;              возвращает индекс полученного блока.
;
;.Proto        long XMM_AllocateExtended(unsigned space);
;
;.Params       space - размер требуемого блока памяти
;                      в килобайтах;
;
;.Return       < 0 - блок не распределен,
;                    код ошибки находится в старшем байте.
;              > 0L  - младший байт содержит индекс
;                      полученного блока памяти.
;
;.Sample       xms_test.c
;**


XMM_AllocateExtended proc near
			 c_begin
			 mov  ah, 9
			 mov  dx,  [bp+4]
          call [XMM_Control]
          or   ax, ax
          mov  ax, dx
			 mov  dx, 0
			 jnz  @success9
          mov  dh, bl
@success9:
			 c_end
XMM_AllocateExtended endp

;**
;.Name         XMM_FreeExtended
;.Title        Освободить блок расширенной памяти
;
;.Descr        Эта функция освобождает блок
;              расширенной памяти, полученный функцией
;              XMM_AllocateExtended().
;
;.Proto        long XMM_FreeExtended(unsigned handle);
;
;.Params       handle - индекс освобождаемого блока памяти;
;
;.Return       < 0 - блок не распределен,
;                    код ошибки находится в старшем байте.
;              0L  - блок освобожден.
;
;.Sample       xms_test.c
;**

XMM_FreeExtended proc near
			 c_begin
          mov  ah, 0Ah
			 mov  dx, [bp+4]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @successA
          mov  dh, bl
@successA:
			 c_end
XMM_FreeExtended endp

;**
;.Name         XMM_MoveExtended
;.Title        Копировать блок расширенной памяти
;
;.Descr        Эта функция копирует блок
;              расширенной памяти, используя структуру
;              struct XMM_Move:
;
;                 struct   XMM_Move {
;                    unsigned long  Length;
;                    unsigned short SourceHandle;
;                    unsigned long  SourceOffset;
;                    unsigned short DestHandle;
;                    unsigned long  DestOffset;
;                 };
;
;.Proto        long  XMM_MoveExtended(struct
;                       XMM_Move *move_descr);
;
;.Params       struct XMM_Move *move_descr -
;                 указатель на структуру, описывающую
;                 что, откуда и куда надо копировать.
;
;.Return       < 0 - ошибка при копировании,
;                    код ошибки находится в старшем байте.
;              0L  - блок скопирован успешно.
;
;.Sample       xms_test.c
;**

XMM_MoveExtended proc near
			 c_begin
          mov  ah, 0Bh
			 mov  si, [bp+4];
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @successB
          mov  dh, bl
@successB:
			 c_end
XMM_MoveExtended endp

;**
;.Name         XMM_LockExtended
;.Title        Заблокировать блок расширенной памяти
;
;.Descr        Эта функция блокирует блок расширенной
;              памяти и возвращает 31 разряд его
;              физического адреса.
;
;.Proto        long XMM_LockExtended(unsigned handle);
;
;.Params       handle - индекс блокируемого блока памяти;
;
;.Return       < 0 - блок не заблокирован,
;                    код ошибки находится в старшем байте.
;              > 0L  - блок заблокирован, функция
;                      возвращает физический адрес блока
;                      памяти.
;
;.Sample       xms_test.c
;**

XMM_LockExtended proc near
			 c_begin
          mov  ah, 0Ch
			 mov  dx, [bp+4]
          call [XMM_Control]
			 xchg ax, bx
			 dec  bx
          jz   XMML_Success
          mov  dh, al
XMML_Success:
			 c_end
XMM_LockExtended endp

;**
;.Name         XMM_UnLockExtended
;.Title        Разблокировать блок расширенной памяти
;
;.Descr        Эта функция разблокирует блок расширенной
;              памяти.
;
;.Proto        long XMM_UnLockExtended(unsigned handle);
;
;.Params       handle - индекс блока памяти;
;
;.Return       < 0 - блок не разблокирован,
;                    код ошибки находится в старшем байте.
;              0L  - блок разблокирован.
;
;.Sample       xms_test.c
;**

XMM_UnLockExtended proc near
			 c_begin
          mov  ah, 0Dh
			 mov  dx, [bp+4]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @successC
          mov  dh, bl
@successC:
			 c_end
XMM_UnLockExtended endp

;**
;.Name         XMM_GetHandleLength
;.Title        Получить длину блока расширенной памяти
;
;.Descr        Эта функция возвращает длину блока
;              расширенной памяти по его индексу.
;
;.Proto        long XMM_GetHandleLength(unsigned handle);
;
;.Params       handle - индекс блока памяти;
;
;.Return       < 0 - произошла ошибка,
;                    код ошибки находится в старшем байте.
;              > 0L  - длина блока в килобайтах.
;
;.Sample       xms_test.c
;**

XMM_GetHandleLength proc near
			 c_begin
          mov  ah, 0Eh
			 mov  dx, [bp+4]
          call [XMM_Control]
          or   ax, ax
          mov  ax, dx
			 mov  dx, 0
			 jnz  @successD
          mov  dh, bl
@successD:
			 c_end
XMM_GetHandleLength endp

;**
;.Name         XMM_GetHandleInfo
;.Title        Получить информацию о блоке расширенной памяти
;
;.Descr        Эта функция возвращает общее
;              количество индексов в системе и
;              содержимое счетчика блокирования для
;              заданного индекса.
;
;.Proto        long XMM_GetHandleInfo(unsigned handle);
;
;.Params       handle - индекс блока памяти;
;
;.Return       < 0 - произошла ошибка,
;                    код ошибки находится в старшем байте.
;              > 0L  - младший байт - общее количество
;                      индексов в системе;
;                      старший байт - счетчик блокирования.
;
;.Sample       xms_test.c
;**

XMM_GetHandleInfo proc near
			 c_begin
          mov  ah, 0Eh
			 mov  dx, [bp+4]
          call [XMM_Control]
          mov  dx, bx
          or   ax, ax
          mov  ax, dx
			 mov  dx, 0
			 jnz  @successE
          mov  dh, bl
@successE:
			 c_end
XMM_GetHandleInfo endp

;**
;.Name         XMM_ReallocateExtended
;.Title        Изменить размер блока расширенной памяти
;
;.Descr        Эта функция изменяет размер выделенного
;              блока расширенной памяти.
;
;.Proto        long XMM_ReallocateExtended(unsigned handle,
;                 unsigned new_size);
;
;.Params       handle - индекс блока памяти;
;              new_size - новый размер блока памяти
;                      в килобайтах;
;
;.Return       < 0 - блок не распределен,
;                    код ошибки находится в старшем байте.
;              > 0L  - младший байт содержит индекс
;                      полученного блока памяти.
;
;.Sample       xms_test.c
;**

XMM_ReallocateExtended proc near
			 c_begin
          mov  ah, 0Fh
			 mov  dx, [bp+4]
			 mov  bx, [bp+6]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @successF
          mov  dh, bl
@successF:
			 c_end
XMM_ReallocateExtended endp

;**
;.Name         XMM_RequestUMB
;.Title        Запросить область UMB
;
;.Descr        Эта функция пытается зарезервировать для
;              программы область UMB
;
;.Proto        long  XMM_RequestUMB(unsigned space);
;
;.Params       space - размер требуемой области
;                      в параграфах;
;
;.Return       < 0 - область UMB не назначена программе,
;                    код ошибки находится в старшем байте;
;                    максимальный размер доступного блока
;                    в младшем слове (16 разрядов);
;              > 0L  - область UMB назначена программе,
;                    младшее слово содержит сегмент блока
;                    UMB, старший - размер выделенного
;                    блока UMB.
;
;.Sample       xms_test.c
;**

XMM_RequestUMB proc near
			 c_begin
          mov  ah, 10h
			 mov  dx, [bp+4]
          call [XMM_Control]
			 xchg bx, ax
			 dec  bx
          jz   RUMB_Success
			 xchg ax, dx
			 mov  dh, dl
RUMB_Success:
			 c_end
XMM_RequestUMB endp

;**
;.Name         XMM_ReleaseUMB
;.Title        Освободить область UMB
;
;.Descr        Эта функция пытается освободить
;              область UMB
;
;.Proto        long  XMM_ReleaseUMB(unsigned segment);
;
;.Params       segment - сегмент освобождаемого блока UMB*
;
;.Return       < 0 - область UMB не освобождена,
;                    код ошибки находится в старшем байте.
;              0L - область UMB освобождена.
;
;.Sample       xms_test.c
;**

XMM_ReleaseUMB proc near
			 c_begin
          mov  ah, 11h
			 mov  dx, [bp+4]
          call [XMM_Control]
          xor  dx, dx
          dec  ax
			 jz   @success10
          mov  dh, bl
@success10:
			 c_end
XMM_ReleaseUMB endp

			 END
