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

Аппаратное обеспечение IBM PC

© Александр Фролов, Григорий Фролов
Том 2, книга 1, М.: Диалог-МИФИ, 1992.

[Назад] [Содеожание] [Дальше]

10.6. Интерфейс с Си

Приведем текст программы, позволяющей программам, составленным на языке программирования Си, использовать функции драйвера расширенной памяти. Эта программа будет работать только в моделях памяти Small и Compact. Для других моделей памяти требуется изменить строки программы, в которых передаваемые функциям параметры извлекаются из стека и тип процедур (FAR):

Аргументы           Small, Compact        Large, Huge

Первый аргумент [bp+4]               [bp+6]
Второй аргумент [bp+6]               [bp+8]


; Это интерфейсный модуль для вызова функций
; 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


Приведем пример программы, демонстрирующей использование некоторых функций XMM:

#include <stdio.h>
#include <conio.h>
#include "sysp.h"

void main(void);
void main(void) {

        long ver, rc, handle;
        static char testmsg[] = "Тестовое сообщение";
        char buf[80];
        char far *ptr;
        int i;
        struct XMM_Move move_d;

// Проверяем, установлен ли драйвер HIMEM.SYS,
// если установлен, выводим его версию.

        if (XMM_Installed()) {
                printf("\nДрайвер HIMEM.SYS установлен.");
                ver = XMM_Version();
                printf("\nВерсия XMM: %4X, изменения: %4x",
                        (short)ver, (short)(ver >> 16));
        }

        else {
                printf("\nДрайвер HIMEM.SYS не установлен.");
                exit(-1);
        }

// Запрашиваем управление областью HMA.

        rc = XMM_RequestHMA(0xffff);
        if(rc) error("Ошибка при запросе области HMA",rc);

        else {

// Открываем линию A20.

                rc = XMM_GlobalEnableA20();
                if(rc) error("Ошибка при разрешении линии A20",rc);

// Копируем тестовое сообщение сначала из
// стандартной памяти в область HMA,
// затем обратно в стандартную память.

                ptr = FP_MAKE(0xffff,0x0010);

                for(i=0; testmsg[i] != 0; i++)
                        ptr[i] = testmsg[i];

                for(i=0; ptr[i] != 0; i++)
                        buf[i] = ptr[i];
                buf[i] = 0;

// Выводим сообщение для проверки.

                printf("\n%s",buf);

// Закрываем линию A20 и отдаем системе область HMA.

                rc = XMM_GlobalDisableA20();
                if(rc) error("Ошибка при запрещении линии A20",rc);

                rc = XMM_ReleaseHMA();
                if(rc) error("Ошибка при освобождении области HMA",rc);
        }

// Получаем блок EMB размером в 1 килобайт.

        handle = XMM_AllocateExtended(1);
        if(handle < 0) error("Ошибка при запросе XMB",handle);

// Копируем тестовое сообщение сначала из
// стандартной памяти в блок EMB,
// затем обратно в стандартную память.

        move_d.Length = strlen(testmsg) + 1;
        move_d.SourceHandle = 0;
        (char far*)move_d.SourceOffset = (char far*)testmsg;
        move_d.DestHandle = handle;
        move_d.DestOffset = 0L;

        rc = XMM_MoveExtended(&move_d);
        if(rc < 0) error("Ошибка при копировании в EMB",rc);

        move_d.Length = strlen(testmsg) + 1;
        move_d.DestHandle = 0;
        (char far*)move_d.DestOffset = (char far*)buf;
        move_d.SourceHandle = handle;
        move_d.SourceOffset = 0L;

        rc = XMM_MoveExtended(&move_d);
        if(rc < 0) error("Ошибка при копировании из EMB",rc);

// Выводим сообщение для проверки.

        printf("\n%s",buf);

// Освобождаем блок EMB.

        rc = XMM_FreeExtended(handle);
        if(rc) error("Ошибка при освобождении XMB",rc);

        exit(0);
}

// Функция для вывода сообщения об ошибке
// и кода ошибки.

int error(char *msg, long rc) {

        rc = (unsigned char)(rc >> 24) ;
        printf("\n%s, код ошибки: %02.2X\n",
                msg, (unsigned char)rc);

}
[Назад] [Содеожание] [Дальше]