11697

Ознайомлення з функціями драйвера EMS

Лабораторная работа

Информатика, кибернетика и программирование

ЛАБОРАТОРНА РОБОТА №13. Тема: Ознайомлення з функціями драйвера EMS. Ціль: Вивчити здатність роботи з розширеною памяттю. Теоретичні відомості. На відміну від розширеної памяті додаткова память за допомогою спеціальної апаратури і програмного забезпечення в

Украинкский

2013-04-10

119.5 KB

1 чел.

ЛАБОРАТОРНА РОБОТА №13.

Тема:  Ознайомлення з функціями драйвера EMS.

Ціль: Вивчити здатність роботи з розширеною пам'яттю. 

Теоретичні відомості.

 На відміну від розширеної пам'яті додаткова пам'ять за допомогою спеціальної апаратури і програмного забезпечення відображується в діапазон адрес, що лежить нижче за межу 1 Мбайт. Такий спосіб придатний для комп'ютерів, що використовують процесор Intel 8086, що не має можливості адресації розширеної пам'яті.

         Щоб зрозуміти, як відбувається відображення, згадаємо розподіл першого мегабайта оперативної пам'яті. Область з адресами від 00000 до 9FFFF - це стандартна пам'ять розміром 640К. (Ми використовуємо тут фізичну 20-розрядну адресу). Діапазон адрес від A0000 до BFFFF використовується відеоадаптерами. Нарешті, 256 Кбайтов з адресами C0000 - FFFFF використовується для BIOS.

         Проте зазвичай BIOS не займає усе 256 Кбайтов адресного простору, залишаючи "вікна" розміром в десятки кілобайт. За допомогою спеціальної апаратури можна відображувати ці вікна на ділянки додаткової пам'яті, як би "підставляючи" ділянки пам'яті під адреси "вікон".

         У практиці побудови обчислювальних систем на основі мікропроцесорів така техніка використовується вже давно. Для комп'ютерів IBM PC/XT/AT корпорації Lotus Development, Intel і Microsoft розробили специфікацію розширеної пам'яті (Expanded Memory Specification - EMS).

        У специфікації EMS як вікно для доступу до додаткової пам'яті використовуються 64 кілобайти, розташовані по адресах C0000h, - EFFFFh. Це вікно в специфікації називається "page frame". Вікно розбивається на чотири сегменти по 16 кілобайт. Уся додаткова пам'ять розбивається на логічні сторінки (logical page) розміром по 16 кілобайт. Будь-яка логічна сторінка може бути відображена на будь-який сегмент вікна доступу. Таким чином, використовуючи чотири сегменти, програма може адресуватися одночасно до будь-яких чотирьох логічних сторінок додаткової пам'яті.

На малюнку схематично показано відображення логічних сторінок додаткової пам'яті на сегменти 64-кілобайтного вікна, розташованого в області адрес ПЗП, :

Перевірка підключення драйвера.

Драйвер додаткової пам'яті встановлює вектор переривання INT 67h таким чином, що цей вектор вказує на заголовок драйвера. Для перевірки підключення драйвера ми можемо, отримавши адресу заголовка, порівняти вісім байтів імені пристрою з рядком "EMMXXXX0". При збігу ми можемо вважати, що драйвер додаткової пам'яті встановлений.

Для перевірки установки драйвера ви можете використовувати наступну функцію, що виконує усі описані дії, :

/*

*.Name         ems_init

*.Title        Функція перевіряє установку драйвера EMS

*.Descr        Ця функція перевіряє наявність драйвера EMS

*.Proto        int ems_init(void);

*.Params       Не використовуються

*.Return       0 - драйвер EMS встановлений;

*              1 - драйвер EMS не встановлений.

*.Sample       ems_test.c

*/

#include <stdio.h>

#include <dos.h>

#include "sysp.h"

int ems_init(void){

               void(void);

               char _far *EMS_driver_name;

               char test_name[8];

               int i;

               EMS_driver_adr = _dos_getvect(0x67);

               FP_SEG(EMS_driver_name) = FP_SEG (EMS_driver_adr);

               FP_OFF(EMS_driver_name) = 10;

               for(i=0; i<8; i++) test_name[i] = EMS_driver_name[i];

               if(strncmp(test_name, "EMMXXXX0", 8) == 0) return(0);

               else return(1);

}

Виклик функцій драйвера.

Для виклику функцій драйвера додаткової пам'яті програма повинна завантажити код функції в регістр AH, код підфункції (зазвичай 0) в регістр AL, і потім викликати переривання INT 67h.

Після повернення з переривання в регістр AH буде записано слово стану. При успішному виконанні функції воно дорівнює 0.

Стандартні функції EMM

Стандартні функції - це невелика підмножина функцій EMM, необхідна для роботи звичайних прикладних програм (не резидентних і не драйверів). Усі ці функції підтримуються EMM версії 3.2.

Отримати багатство EMM

На вході:       AX = 4000h.

На виході:      AH = байт стану EMM.

Ця функція використовується для перевірки стану драйвера EMM. Вона повинна використовуватися тільки після того, як програма переконалася в наявності драйвера EMM.

Для отримання стану EMM використовуйте наступну функцію:

/*

*.Name         ems_stat

*.Title        Визначення стану драйвера EMS

*.Descr        Ця функція повертає байт стану

*              драйвера EMS

*.Proto        char ems_stat(void);

*

*.Params       Не використовуються

*

*.Return       Байт стану драйвера EMS

*

*.Sample       ems_test.c

*/

#include <stdio.h>

#include <dos.h>

#include "sysp.h"

char ems_stat(void){

union REGS reg;

struct SREGS sreg;

reg.x.ax = 0x4000;

int86(0x67, &reg, &reg);

return(reg.h.ah);

}

Отримати сегмент вікна

На вході:       AX = 4100h.

На виході:      AH = байт стану EMM;

BX = сегмент вікна для доступу до логічних

сторінкам додаткової пам'яті.

Функція дозволяє отримати сегмент 64-кілобайтного вікна, використовуваного драйвером EMS для доступу до логічних сторінок розширеної пам'яті.

/*

*.Name         ems_fram

*.Title        Визначення сегменту вікна доступу

*

*.Descr        Ця функція повертає сегментну адресу

             *              вікна, яке використовується для доступу до

            *              додатковій пам'яті.

*.Proto        char ems_fram(unsigned *frame);

*.Params       unsigned *frame - Покажчик на змінну

               *                 у яку буде записаний сегментний

                *                 адреса вікна доступу.

*.Return       Сосотояние EMM.

*.Sample       ems_test.c

*/

#include <stdio.h>

#include <dos.h>

#include "sysp.h"

char ems_fram(unsigned *frame){

union REGS reg;

struct SREGS sreg;

reg.x.ax = 0x4100;

int86(0x67, &reg, &reg);

*frame = reg.x.bx;

return(reg.h.ah);

}

Отримати розмір доступної пам'яті EMS

На вході:       AX = 4200h.

На виході:      AH = байт стану EMM;

DX = загальна кількість 16-кілобайтних

сторінок EMS в системі;

BX = число доступних нині

сторінок EMS.

Ця функція дозволяє вам отримати інформацію про наявність і доступність сторінок додаткової пам'яті.

/*

*.Name         ems_page

*.Title        Визначення кількості сторінок EMS

*

*.Descr        Ця функція призначена для визначення

            *              загальної кількості сторінок EMS і кількості

            *              сторінок, доступних нині.

*.Proto        char ems_page(unsigned *total, unsigned *free);

*.Params       unsigned *total - покажчик на змінну

               *                 у яку буде записано загальну кількість

                *                 сторінок пам'яті EMS;

             *              unsigned *free - покажчик на змінну

                *                 у яку буде записано кількість

               *                 доступних сторінок пам'яті EMS;

*.Return       Сосотояние EMM.

*.Sample       ems_test.c

*/

#include <stdio.h>

#include <dos.h>

#include "sysp.h"

char ems_page(unsigned *total, unsigned *free){

union REGS reg;

reg.x.ax = 0x4200;

int86(0x67, &reg, &reg);

*total = reg.x.dx;

*free  = reg.x.bx;

return(reg.h.ah);

}

Відкрити індекс EMM

На вході:       AX = 4300h;

BX = потрібна в цьому пулі кількість

логічних сторінок.

На виході:      AH = байт стану EMM;

DX = індекс пулу EMS, він використовуватиметься

у операціях з пулом логічних сторінок.

Ця функція дозволяє замовити пул логічних сторінок (тобто деяку сукупність логічних сторінок додаткової пам'яті). Отриманому пулу надається індекс (handle), який вказує на пул і використовується в усіх операціях з пулом.

/*

*.Name         ems_open

*.Title        Відкриття індексу пулу сторінок EMS

*.Descr        Ця функція відкриває індекс пулу сторінок

             *              EMS, роблячи доступними логічні сторінки

             *              додатковій пам'яті.

*.Proto        int ems_open(int n_pages, int *handle);

*.Params       int n_pages - кількість необхідних логічних

                *                 сторінок;

             *              int *handle - покажчик на слово, в яке

                *                 буде записаний індекс отриманого пулу.

*.Return       Байт стану драйвера EMS

*.Sample       ems_test.c

*/

#include <stdio.h>

#include <dos.h>

#include "sysp.h"

int ems_open(int n_pages, int *handle){

union REGS reg;

reg.x.ax = 0x4300;

reg.x.bx = n_pages;

int86(0x67, &reg, &reg);

*handle = reg.x.dx;

return(reg.h.ah);

}

Відобразити пам'ять

На вході:       AH = 44h;

AL = номер фізичної сторінки вікна доступу

(від 0 до 3);

BX = номер логічної сторінки з числа

сторінок (, що знаходяться в кулі, від 0 до n - 1,

де n - кількість логічних сторінок

у кулі);

для версії EMS 4.0 завдання значення

00FFFFh призводить до заборони відображення

фізичних сторінок пулу, для дозволу

їх відображення необхідно викликати цю

функцію ще раз, вказавши правильний

номер сторінки;

DX = індекс EMM, отриманий від функції 43h.

На виході:      AH = байт стану EMM.

Функція виконує відображення (прив'язку) однієї з логічних сторінок пулу до одного їх чотирьох 16-кілобайтних сегментів вікна перегляду, тобто до фізичних сторінок.

/*

*.Name         ems_map

*.Title        Відобразити пам'ять EMS

*

*.Descr        Ця функція відображує логічні сторінки

             *              пулу додаткової пам'яті на фізичні.

*.Proto        int ems_map(int phys_page, int log_page

                        *                          int handle);

*.Params       int phys_pages - номер фізичної сторінки

                *                 вікна доступу (від 0 до 3), на яку необхідно

                *                 відобразити логічну сторінку пулу;

             *              int_log_page - номер логічної сторінки пулу;

             *              int *handle - індекс отриманого пулу;

*.Return       Байт стану драйвера EMS

*.Sample       ems_test.c

*/

#include <stdio.h>

#include <dos.h>

#include "sysp.h"

int ems_map(int phys_page, int log_page, int handle){

union REGS reg;

reg.h.ah = 0x44;

reg.h.al = phys_page;

reg.x.bx = log_page;

reg.x.dx = handle;

int86(0x67, &reg, &reg);

return(reg.h.ah);

}

Закрити індекс EMM

На вході:       AX = 4500h;

DX = індекс EMM.

На виході:      AH = байт стану EMM.

Функція звільняє усі логічні сторінки пулу. Після звільнення ці сторінки можуть бути повторно розподілені.

/*

*.Name         ems_clos

*.Title        Закриття індексу пулу сторінок EMS

*.Descr        Ця функція закриває індекс пулу сторінок

            *              отриманий функцією ems_open().

*.Proto        int ems_clos(int *handle);

*.Params       int *handle - покажчик на слово, в яке

                *                 буде записаний індекс отриманого пулу.

*.Return       Байт стану драйвера EMS

*.Sample       ems_test.c

*/

#include <stdio.h>

#include <dos.h>

#include "sysp.h"

int ems_clos(int *handle){

union REGS reg;

reg.x.ax = 0x4500;

reg.x.dx = *handle;

int86(0x67, &reg, &reg);

return(reg.h.ah);

}

Отримати номер версії EMM

На входsе:      AX = 4600h.

На виході:      AH = байт стану EMM;

AL = номер версії в двійково-десятковому (BCD)

форматі, 32h відповідає версії 3.2.

Версія 4.0 EMM підтримує більше функцій по управлінню додатковою пам'яттю, чим версія 3.2. Перш ніж використовувати такі функції, слід визначити номер використовуваної версії EMM за допомогою функції 46h.

/*

*.Name         ems_ver

*.Title        Визначення версії драйвера EMS

*.Descr        Ця функція повертає номер версії

             *              драйвера EMS в двійково-десятковому форматі.

*.Proto        int ems_ver(char *ver);

*.Params       char *ver - покажчик на байт, в який

                *                 буде записаний номер версії.

*.Return       Номер версії драйвера EMS у форматі BCD

*.Sample       ems_test.c

*/

#include <stdio.h>

#include <dos.h>

#include "sysp.h"

int ems_ver(char *ver){

union REGS reg;

reg.x.ax = 0x4600;

int86(0x67, &reg, &reg);

*ver = reg.h.al;

return(reg.h.ah);

}

Програма, використовуюча EMS

Приведена нижче програма демонструє використання основних функцій EMM :

#include <stdio.h>

#include <conio.h>

#include "sysp.h"

void main(void);

void main(void){

               unsigned frame, err;

               unsigned total, free;

               unsigned handle;

               char ver;

// Це повідомлення буде переписано спочатку з

// області стандартної пам'яті в область додаткової

// потім назад в область основної.

               static char test_msg[] = "Тестове повідомлення для "

                                               "                                                "записи в область EMS".;

               char buf[80];

               char _far *ptr;

               int i;

// Перевіряємо, чи встановлений драйвер EMS.

               if(ems_init() != 0){

                               printf("\nДрайвер EMS не встановлений".);

                               exit(- 1);

               }

// Якщо драйвер встановлений, визначаємо його стан.

               printf("\nДрайвер EMS встановлений, стан: %02.2X".,

                               ems_stat());

// Виводимо номер версії драйвера

               if((err = ems_ver(&ver)) != 0){

                               printf("\nОшибка: %02.2X", err);

                               exit(- 1);

               }

               printf("\nВерсия EMM: %02.2X", ver);

// Визначуваний сегмент вікна доступу

               if((err = ems_fram(&frame)) != 0){

                               printf("\nОшибка: %02.2X", err);

                               exit(- 1);

               }

               printf("\nСегмент вікна доступу : %04.4X",

                               frame);

// Визначаємо загальну кількість сторінок і

// кількість доступних сторінок.

               if((err = ems_page(&total, &free)) != 0){

                               printf("\nОшибка: %02.2X", err);

                               exit(- 1);

               }

               printf("\nОбщее кількість сторінок EMS : %d"

                        "                         "\nКоличество доступних сторінок : %d"

                                                 total, free);

// Замовляємо пул в додатковій пам'яті.

               if((err = ems_open(free, &handle)) != 0){

                               printf("\nОшибка: %02.2X", err);

                               exit(- 1);

               }

// Відображуємо нульову фізичну сторінку

// на нульову логическуб сторінку пулу.

               if((err = ems_map(0, 0, handle)) != 0){

                               printf("\nОшибка: %02.2X", err);

                               exit(- 1);

               }

// Конструюємо покажчик на фізичну сторінку.

               ptr = FP_MAKE(frame, 0);

// Копіюємо тестове повідомлення в

// додаткову пам'ять.

               printf("\nКопируем в EMS: %s", test_msg);

               for(i=0; test_msg[i] != 0; i++)

                               ptr[i] = test_msg[i];

// Тепер копіюємо це повідомлення назад

// у стандартну пам'ять.

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

                               buf[i] = ptr[i];

               buf[i] = 0;

// Виводимо повідомлення на екран для

// перевірки.

               printf("\nСкопировано з EMS: %s", buf);

 // Закриваємо пул.

               if((err = ems_clos(&handle)) != 0){

                               printf("\nОшибка: %02.2X", err);

                               exit(- 1);

               }

               exit(0);

}

Коди помилок

Усі функції EMM повертають код помилки в регістрі AH :

Код

Помилка

0000h

Немає помилки, нормальне завершення

80h

Внутрішня помилка драйвера EMM

81h

Помилка апаратури EMS -памяти

82h

EMM зайнятий

83h

Неправильний індекс пулу

84h

Неправильний номер запрошеної функції

85h

Більше немає доступних індексів пулів

86h

Помилка при виконанні збереження або відновлення контексту відображення

87h

Запрошено більше пам'яті, чим загальна кількість доступної EMS -памяти

88h

Запрошено більше сторінок, чим доступно

89h

Не можна відкрити індекс порожнього пулу

8Ah

Пул не містить так багато сторінок

8Bh

Неправильне відображення, задані номери

фізичних сторінок, відмінні від 0 - 3

8Ch

Переповнена область збереження контексту відображення

8Dh

Багатократне збереження контексту для одного пулу

8Eh

Спроба відновлення незбереженого контексту

8Fh

Неправильний номер підфункції в регістрі AL

90h

Неправильний тип атрибуту

91h

Не підтримується неруйнована пам'ять

92h

Сталося перекриття початковою і результуючою областей (це не помилка, а попередження)

93h

Область призначення, задана індексом, занадто мала

94h

Стандартна пам'ять перекривається додатковою пам'яттю

95h

Занадто велике зміщення при пересилці блоку

96h

Занадто великий розмір блоку, більше 1 мегабайта

97h

Задані однакові початковий і результуючий індекси

98h

Заданий неправильний тип пам'яті (зміщення 4)

A0h

Заданому імені не відповідає жоден пул

A1h

Задане ім'я вже існує

A2h

Довжина початкової області більше 1 мегабайта

A3h

Вміст заданого блоку даних невірний

A4h

Доступ до цієї функції заборонений

Індивідуальне завдання.

Визначити наявність встановленого в системі драйвера ЕММ. Навести приклади використання його функцій. Отримати версію драйвера і інформацію про структуру і об'єм доступної пам'яті.


 

А также другие работы, которые могут Вас заинтересовать

63016. «Пори року» Позакласний захід з географії 22.69 KB
  У ліс завітаю я знову На тиху сердечну розмову І сонцем пропалені лиця Я чую зозулі кування Берізок тремтивих зітхання Тонкі білокурі сестриці Сплели свої вінки в косиці. Учениця: квіти підсніжники – провісники тепла символ сподівань на краще майбутнє.