Глава 22. О том, какая в MS DOS имеется память и как ее использовать.

- Все говорят пет правды на зем­ле, по правды пет и выше!

Моцарт и Сальери ПушкинА. С.

Проблема различных видов памяти существует в MS DOS и является следствием того, что данная операционная система работает в реальном режиме, а также некото­рой непродуманности ее развития. Изначально эта операционная система была заду­мана как однозадачная среда61. Именно здесь я вижу изъян, который и привел в конеч­ном итоге тем сложностям, которые постоянно сопровождали развитие данной опе­рационной системы. Справедливости ради следует отметить и лепту, которую вне­сла в эту проблему фирма Intel с ее двухкомпонентными адресами.

 

 

 

 

Расширенная память (EXTENDED MEMORY)

1 Мб.

Я к А - 64 Кб.

ROM

Верхняя память

имв

640 Кб.

Страницы дополнительной памяти (EXPANDED MEMORY}

Видеопамять

О Кб.

Основная память

640 Кб.

Рис. 22.1. Карта памяти персонального компьютера.

На Рис. 22.1 представлена схема различных видов памяти, которая может присут­ствовать у IBM-подобного компьютера в среде MS DOS. Этот рисунок следует срав­нить с Рис. 2.3 (глава 2). Перечислю эти виды памяти: основная, или базовая, память, дополнительная память, верхняя память, расширенная память, НМЛ - High Memory Area - область старшей памяти - представляет собой фактически первые 64Кб расши­ренной памяти.

I. Дополнительная память.

Задолго до появления 286-х компьютеров стало ясно, что 640 Кб памяти яв­ляются серьезным препятствием для развития программного обеспечения. В нача­ле 1985 года три фирмы: LOTUS, INTEL, MICROSOFT - выпустили специфика­цию, позволяющую использовать на компьютерах XT дополнительную память. Эта спецификация получила название LIM EMS (LIM - по названию фирм, т.е. Lotus-IBM-Microsoft, EMS - EXPANDED MEMORY SPECIFICATION). В настоящее вре­мя используется спецификация версии 4.0, которая может поддерживать до 32 Мб памяти.

Установка дополнительной памяти происходила в два этапа. В свободный слот материнской платы устанавливалась плата с дополнительным ОЗУ. Для работы с этой платой должен был устанавливаться драйвер EMM. EMM делит всю ОЗУ на плате на ряд блоков по 16 Кб каждый, называемых логическими страницами. Затем он находит неиспользуемый участок памяти размером 64Кб в области между 640 Кб и 1М, делит его на четыре физические страницы по 16 Кб каждая. Эта область размером 64Кб

называется страничным блоком.

Чтобы получить доступ к дополнительной памяти, необходимо:

1. Запросить у EMM определенное количество логических страниц.

2. Если такое количество страниц существует, то EMM резервирует эти страницы и возвращает их дескриптор. Данный набор логических страниц в дальнейшем определяется данным дескриптором.

3. Поставить в соответствие логические и физические страницы - отобразить ло­гические страницы на физические.

4. Поскольку адресное пространство, где помещаются физические страницы, на­ходится в пределах Мб, то доступ к дополнительной памяти осуществляется обычными командами микропроцессора.

Отображая на физические страницы те или иные логические страницы, вы можете получить доступ ко всей дополнительной памяти.

Дополнительная память необязательно должна быть установлена на плате62. На компьютерах, начиная с 80286-го, появилась расширенная память (см. ниже). Специальные драйверы могут конвертировать расширенную память в дополнитель­ную память. На ЛТ386 и выше это такие программы, как EMM386.EXE и пакет QEMM, которые, предоставляя сеанс MS DOS, также эмулируют рассматриваемые виды памяти.

Лвтор, к сожалению, не встречал компьютеры с дополнительной памятью на плате.

П. Интерфейс с драйвером EMM. (EXPANDED MEMORY MANAGER)

Cвязь с драйвером осуществляется через прерывание 67Н. В регистр ЛН следует поместить номер функции. После выполнения функции в АН находится результат вы­полнения. Если возвращается 0, то функция выполнена успешно. Здесь перечислены не все функции драйвера, но их более чем достаточно для программного использования.

Е Состояние драйвера EMM. Вход: АН-40Н Выход:

ЛН - ООН память готова к работе, 80Н внутренняя ошибка, 81Наппаратная ошибка.

2. Чтение адреса страничного окна.

Вход:

ЛН-41Н

Выход:

ЛН - ООН нормальное завершение, ВХ - сегментный адрес страничного окна, АН - 80Н внутренняя ошибка, АН - 8 Ш аппаратная ошибка.

3. Чтение числа страниц EMS памяти. Вход:

АН-42Н

Выход:

АН - ООН нормальное завершение,

- количество свободных страниц, DX - общее количество страниц EMS памяти, ЛН - 80Н внутренняя ошибка, АН - 81Наппаратная ошибка.

4. Выделение страниц EMS памяти.

Вход: АН-43Н

ВХ - число требуемых логических страниц.

Выход:

ЛН - ООН нормальное завершение,

DX - код описателя для доступа к выделенным страницам,

ЛН - 80Н внутренняя ошибка,

ЛН - 81Н аппаратная ошибка,

ЛН - 85Н свободных описателей нет,

ЛН - 87Н недостаточно свободных страниц,

ЛН - 88Н запрос на выделение страниц отсутствует.

5. Задание отображения.

Вход: АН-44Н

AL - номер физической страницы (0-3), ВХ - номер логической страницы (нумерация также с 0), DX - описатель.

Выход:

ЛН - ООН нормальное завершение, АН - 80Нвнутренняя ошибка, АН - 81Наппаратная ошибка, ЛН - 83Н неверный описатель, ЛН - 8ЛН неверная логическая страница, ЛН - 8ВН неверная физическая страница.

6. Освобождение страниц EMS.

Вход: АН-45Н

- описатель.

Выход:

ЛН - ООН нормальное завершение, АН - 80Н внутренняя ошибка, АН-81Наппаратная ошибка, ЛН - 83Н неверный описатель, ЛН - 85Н ошибка при сохранении и восстановлении.

7. Определение версии драйвера EMM.

Вход: АН-46Н

Выход:

АН - ООН нормальное завершение, AL - номер версии драйвера EMM, АН - 80Н внутренняя ошибка, АН - 81Н аппаратная ошибка.

8. Запоминание карты отображения.

Вход: АН-47Н

DX - описатель.

Выход:

ЛН - ООН нормальное завершение,

АН - 80Н внутренняя ошибка, АН-81Наппаратная ошибка,

ЛН - 83Н неверный описатель,

ЛН - 8ЕН память карты отображения не содержит записи для данного описателя.

9. Восстановление карты отображения. Вход: АН-48Н DX-описатель.

Выход:

АН - ООН нормальное завершение, АН - 80Н внутренняя ошибка, АН - 81Наппаратная ошибка, АН - 83Н неверный описатель,

АН - 8ЕН память карты отображения не содержит записи для данного описателя.

10. Чтение числа описателей. Вход:

АН-4ВН.

Выход:

АН - ООН нормальное завершение, ВХ - число выделенных описателей, АН - 80Н внутренняя ошибка, АН - 81Наппаратная ошибка.

11. Чтение числа выделенных страниц. Вход:

АН-4СН

- описатель.

Выход:

АН - нормальное завершение,

- число выделенных страниц, АН - 80Н внутренняя ошибка, АН - 81Наппаратная ошибка. АН - 83Н неверный описатель.

12. Чтение информации обо всех описателях. Вход:

АН-4БН

ЕБ - адрес сегмента массива, Б1 - смещение массива.

Выход:

АН - ООН нормальное завершение,

ВХ - число выделенных логических страниц, АН - 80Н внутренняя ошибка, АН - 81Н аппаратная ошибка.

В случае нормального завершения область указанной памяти будет заполнена ин­формацией. Информация будет состоять из записей. Каждая запись - это два слова, первое слово - описатель, второе - количество выделенных страниц.

Ниже представлена программа, демонстрирующая работу с дополнительной па­мятью.

DATA SEGMENT

ТЕХТ1 DB 'Ошибка при работе с драйвером EMM! ',13,10, ' $ ' ТЕХТ2 DB  'Недостаточное количество страниц.',13,10,'$'

STRING DB    'Эта строка для демонстрации работы со' DB  1 страницами памяти EMS.',13,10, ' $ '

DATA ENDS

_ST   SEGMENT STACK

DB   100 DUP(?) _ST ENDS CODE SEGMENT

ASSUME CS:CODE,   DS:DATA, SS:_ST

BEG:

/начальная установка регистров

MOV AX,DATA

MOV DS,AX /установить  флаг   обработки строк

CLD

/проверка наличия драйвера EMM MOV АН,4ОН

INT 67H OR    АН,АН

JZ OKI

CALL ERR JMP DOS

OKI:

/чтение  адреса сегмента  страничного окна MOV АН,41Н

67H

АН, АН

OK2

INT OR JZ CALL

JMP

ERR

DOS

ОК2:

MOV    ES,BX   /сегментный адрес  EMS памяти

/чтение числа страниц EMS памяти MOV АН,42Н 67H АН, АН

ОКЗ

INT

OR

JZ

CALL. ERR

JMP DOS

ОКЗ:

CMP JNB LEA

CALL JMP

BX, 2

OK4

DX,TEXT2

PRINT DOS

0К4 :

;выделяем одну страницу MOV АН,43Н

MOV    ВХ,1 INT 67Н OR      АН, АН

JZ 0К5 CALL ERR

JMP DOS

0K5 :

MOV    BP,DX  /сохраним описатель /отображаем страницу на  физическую область MOV    АН,4 4Н AL, О ВХ, о 67H АН, АН 0 Кб

ERR

DOS ОКб:

/копируем строку STRING

LEA

DI, DI

MOV

MOV

INT

OR

JZ

CALL

JMP

XOR

на  страницу О

LOO:

AL,DS:[SI] ES:[DI],AL

SI

DI

MOV MOV INC

INC

CMPAL,' $ ' JNZ LOO /выделяем еще одну MOV AH,43H MOV BX, 1 INT 67H OR    AH,AH JZ OK7

CALL ERR JMP DOS

OK7 :

ее

MOV AH,44H MOV AL, 1 MOV BX, 0

16-4072

страницу

INT 67H JZ OK8 CALL ERR JMP DOS

OK8:

; копируем первую страницу на вторую ;ES-Ha страницу 1,   DS-на страницу О

MOV AX,ES

MOV DS,AX

ADD AX,1024   /начало страницы 1

MOV ES,AX

XOR  SI,SI

XOR DI,DI

MOV CX,16*1024

L001:

MOV AL,DS:[SI] MOV  ES : [DI] , AL

INC SI inc DI LOOP L001

/освобождаем первую  страницу    (первый описатель) XCHG DX,BP MOV АН,45Н INT 67H OR      АН,АН JZ OK9

CALL ERR

JMP DOS

OK9:

MOV DX,BP

; отображаем    страницу на  вторую физическую страницу

MOV АН,44Н

MOV AL,2

MOV ВХ, 0

INT 67H

JZ ОК10

CALL ERR

JMP DOS

OK10:

;проверяем содержимое PUSH DX

MOV    DX,32*1024

CALL PRINT POP DXстраницы

CLOSE:

MOV АН,45Н

. INT 67H /выход в DOS DOS:

MOV

INT 2lH

процедур

/процедура  вывода   сообщения   об ошибке

ERR PROC

PUSH DS PUSH AX

LEA DX,TEXT1 MOV    АХ,DATA MOV DS,AX

CALL PRINT POP AX

POP DS

RET ERR ENDP

вывода   строки   на экран

PRINT PROC

MOV AH, 9 . int 21H

RET PRINT ENDP CODE ENDS

END BEG

PMC. 22.2. Пример использования дополнительной памяти.

В программе на Рис. 22.2 есть один недостаток: она не проверяет, установлен ли вооб­ще драйвер EMM. Рассмотрим теперь, как это делается. Алгоритм обнаружения драйвера EMM основан натом, что если драйвер установлен, то в системе появляется устройство с именем "ЕММХХХХО". Поэтому можно попытаться открыть файл с таким именем при помощи функции 3DH. Если открытие произошло, то теперь нужно проверить, нетли на дискетакого файла. Для этого можно воспользоваться функцией DOS44H - ее подфунк-циейО. Крометого, необходимо проверить, доступно ли устройство для ввода. Это можно сделать при помощи подфункции 7 той же функции 44Н. Ниже (Рис. 22.3) представлена простая программа, правильно определяющая присутствие драйвера EMM.

CODE SEGMENT

ASSUME CS : CODE, DS: CODE ORG 100H

16*,-открыть устройство ЕММХХХХО

MOV АН,3DH

MOV AL,О

LEA DX,STR_EMM

INT 21H

JC NO_EMMl /проверить,  нет ли файла с таким именем

MOV ВХ,АХ

MOV АХ,4400Н

INT 21H

JC NO_EMM

/присутствие 7-го бита означает,   что это не файл

TEST DX,80H

JZ NO__EMM /проверить статус устройства

MOV АХ,4407Н

INT 21H

JC NO_EMM

CMP AL,0

JZ NO_EMM

LEA DX,STR2

JMP  SHORT KONEC NO_EMM:

LEA DX,STR1

KONEC:

MOV AH,9

INT 21H ./закрыть устройство

CALL CLOSE

RET N0_EMM1:

LEA DX,STR1 MOV AH,9

INT 21H

RET

/блок сообщений " STR_EMM    DB   "ЕММХХХХО", 0

STR1 DB   "Драйвер EMM отсутствует", 13,10,'$'

STR2 DB   "Драйвер EMM присутствует", 13,10, '$'

/процедура закрытие устройства  или файла CLOSE PROC

MOV АН,ЗЕН

CLOSE ENDP CODE ENDS ■

END BEGIN

Рис. 22.3 Программа, определяющая присутствие драйвера EMM.

Другой способ проверки присутствия драйвера EMM в системе основан на том, что вектор 67Ндолжен указывать в тело драйвера. Более того, на расстоянии 10 байт в сторону старших адресов от точки, куда указывает вектор, располагается строка 'ЕММХХХХО'. Проверка наличия такой строки и будет являться проверкой наличия в системе драйвера. Однако этот способ не слишком надежен, так как ничто не мешает какой-нибудь программе перенаправить этот вектор на свою подпрограмму.

III. Расширенная память.

Расширенная память - это память с адресами свыше одного мегабайта. Мы стал­кивались с ней в главах 5 и 20 (см. Рис. 5.2 и 20.2). В главе 5 был показан доступ к этой памяти посредством прерывания       а в главе переходом в

защищенный режим. Драйвер HIMEM.SYS также предоставляет возможности рабо­ты с расширенной памятью. Это интерфейс более высокого уровня, потому что позво­ляет использовать расширенную память совместно нескольким программам. Доступ к расширенной памяти посредством прерывания считается в настоящее время ус­таревшим. Драйвер HIMEM.SYS блокирует этот доступ. Kni04lNT15=N, гдеИ - объем расширенной памяти, доступ к которой можно получить посредством прерывания 15Н, позволяет разблокировать его для Ваших программ.

IV. Область НМА.

Область НМА (HIGH MEMORYAREA) расположена сразу за системным ROM BIOS (выше 1 Мб) и имеет размер приблизительно 64 Кб. Своему существованию она цели­ком обязана эмуляции процессором 80286 процессора 8088. Максимальный полный ад­рес, по которому может обратиться процессор 8088, составляет FFFF:OO0F, что соответ­ствует 20 адресным линиям. Если увеличить это значение на 1 до произойдет цикличес­кий перенос, и значение адреса станет 0000:0000. Таким образом, для процессора 8088 память с адресами FFFF:0010 - FFFF:FFFF (это 64Кб без 16байт) становится невиди­мой. Для процессора 80286 эта проблема может быть решена путем использования ад­ресной линии А20. Для совместимости, однако, процессор 80286 (атакже 80386ит.д.) в обычном состоянии (отключена адресная линия А20) ведет себя так же, как и 8088.

НМА фактически является началом расширенной памяти. Доступ к НМА коррект­но можно осуществить, используя интерфейс драйвера HIMEM.SYS (см. ниже). Начи­ная с версии 5.0, MS DOS умеет забрасывать в НМА часть своих файлов (DOS=HIGH).

V. Верхняя память (UMB).

UMB - сокращение английского названия UPPER MEMORY BLOKS, т.е. блоки верхней памяти. Как и откуда она может появиться? Область памяти между 640Кб и 1 Мб зарезервирована для видеобуферов и ПЗУ. Однако многие блоки в этой области оказываются неиспользуемыми. В частности, именно сюда помещается дополнитель­ная память.

Такие драйверы, как EMM386.EXE, С-ЕММидр., переводят компьютер в виртуаль­ный режим. В этом режиме (он существует, начиная с 386-го процессора) посредством страничной организации можно перенаправить операции чтения или записи из одной области пространства в другую. Таким образом, появляется возможность загружать ре­зидентные программы и драйверы в UMB, тем самым освобождая основную память.

VI. Интерфейс с драйвером HIMEM.SYS.

Драйвер HIMEM.SYS предоставляет возможность работать с тремя видами памя­ти: расширенной, НМАи UMB. Длятого чтобы использовать возможности драйвера, программадолжна:

Е   Определить его наличие в памяти. Это осуществляется посредством прерыва­ния 2FH:

MOV АХ, 4300Н INT 2FH

CMP AL,80H    ;если в AL 80Н, то драйвер установлен JNE NOHIM

2.   Определить 32-разрядный адрес точки входа драйвера:

ADR_HIM_OFF DW ? ADR_HIM_SEG DW ?

MOVAX,4310H

INT 2FH

MOV WORD PTR CS:ADR_HIM_OFF,BX MOV WORD PTR CS:ADR HU\t SEG,ES

Вызов функции драйвера осуществляется командами: MOV АН, 8 -номер функции

CALL DWORD PTR CS:ADR_HIM_OFF ;длинный вызов

Может возникнуть вопрос, почему вызов функции не осуществить посредством того же прерывания 2FH. Но дело в том, что данное прерывание может исполь­зоваться многими программами, и, следовательно, выполнение его может силь­но замедлиться.

3. Драйвер предоставляет возможность работать с 18 функциями, из которых 8 предназначены для работы с расширенной памятью, по 2 - для работы с НМА и UMB, а также 6 дополнительных функций. Вот эти функции.

Номер версии.

Вход:    АН-ОН

Выход: АХ - номер версии,

ВХ- внутреннийномер,

БХ - флаг, если есть НМЛ. Выделение НМА. Вход:    АН - 1Н,

БХ- размер в байтах Выход: АХ - 1, если успешно

Освобождение НМА.

Вход: АН-2Н

Выход:  АХ-1, если успешно

Глобальное разрешение А20

Вход: АН-ЗН

Выход: АХ-1, если успешно

Глобальное запрещение А20 Вход: АН-4Н

Выход:

Локальное разрешение А20.

Вход: АН-5Н

Выход: АХ-1, если успешно

Локальное запрещение А20. Вход: АН-6Н

Выход:

Запрос состояния А20. Вход: АН-7Н Выход: АХ-флаг,

ВЬ-кодошибки

Запрос свободных блоков расширенной памяти. Вход: АН-8Н

Выход: АХ - наибольший свободный блок

БХ- общий размер свободной памяти.

Выделение свободных блоков расширенной памяти. Вход: АН-9Н

БХ- размер памяти в Кб. Выход:  БХ-описатель

Освобождение расширенной памяти. Вход: АН-ОАН

БХ - описатель

Копирование в расширенную память. Вход: АН-ОВН

DX - описатель Выход:  DS:SI - указатель на структуру

Смещение

Тип

Содержание

0

DWORD

Размер

4

WORD

Дескриптор источника

6

DWORD

Адрес источника

10

WORD

Дескриптор источника

12

DWORD

Адрес источника

Блокирование расширенной памяти. Вход: АН-ОСН

DX - описатель Выход:  DX:BX - 32-разрядный адрес блока

Разблокирование расширенной памяти. Вход:    АН-ООН

DX - описатель

Выход:

Информация о расширенной памяти.

Вход: АН-ОЕН

DX - описатель

Выход:  ОХ - размер блока в Кб,

ВН - число запретов на блок,

BL - число еще свободных описателей

Изменение размера расширенной памяти. Вход: АН-ОРН

- описатель Выход:  ВХ-новый размер в Кб,

- описатель

Выделение иМВ. Вход:    АН-ЮН

DX - необходимый размер в параграфах. Выход:  ВХ-сегмент,

БХ- действительный размер в параграфах.

Освобождение ЦМВ. Вход:    АН-ПН

ВХ - сегмент.

Большинство указанных функций возвращает в регистр АХ код результата. Если функция выполнена успешно, то в регистр АХ помещается 1, если нет, то 0. Данные функции эмулируются драйвером QEMM с полностью идентичным доступом.

Ниже приведен пример использования НМА. Если память свободна (там может находиться часть MS DOS), то Вы можете использовать ее в своих программах, напри­мер, для хранения данных.

DATA SEGMENT

ТЕХТ1  DB   'Драйвер не установлен.', 13,10, '$' ТЕХТ2  DB   'Нехватка НМА',13,10,'$' ТЕХТЗ DB   'Проверка!',13,10, ■$■

DATA ENDS

STT SEGMENT STACK

DB   100 DUP(?)

STT ENDS CODE SEGMENT

ASSUME  CS:CODE,   DS:DATA,    SS:STT

BEGIN:

;--сегмент данных MOV AX,DATA MOV DS,AX

;—определяем наличие драйвера

MOV AX,4300H

INT 2FH

CMP AL,8 0H

JNE NO_HIM

JMP SHORT YES NO_HIM:

LEA

MOV AH,9

INT 21H JMP KON

YES:

;—определяем точку входа MOV AX,4310H

INT 2FH

MOV WORD   PTR CS:ADR_HIM_OFF,BX MOV WORD   PTR CS : ADR__HIM_SEG, ES ;—запрашиваем НМА MOV    AH, 1

MOV    DX,20     ; просим 2 0 байт CALL   DWORD   PTR CS:ADR_HIM_OFF

CMP   AX, 1 ■ JNZ     NO OKразрешаем

MOV АН, 3

CALL  DWORD  PTR CS:ADR_HIM_OFF

CMP   AX, 1

JNZ NO_OK JMP   SHORT OK

NO_OK:

выделить  не удалось LEA DX,TEXT2 . MOV AH,9

INT 21H ,-освобождаем НМА . MOV АН, 2H

CALL  DWORD  PTR CS:ADR_HIM_OFF ;запрещаем A2 0 MOV   AH, 4

CALL  DWORD  PTR CS:ADR_HIM_OFF

JMP KON

OK:

строку из DATA

MOV AX,OFFFFH

MOV ES,AX

LEA SI,TEXT3

MOV DI,010H

память сразу за 1MB

LOO:

MOV MOV CMP

JZ

INC INC JMP

ALL:

; —теперь

AL, [SI] ES:[DI],AL AL,'$'

ALL

DI

SI

SHORT LOO

печатаем MOV DX, 010H MOV AX,ES MOV DS,AX

;—DS:DX указывает на память сразу за 1MB

MOV АН,9

INT 21H ; —освобождаем НМА

MOV BX,ES

MOV АН,2Н

CALL   DWORD   PTR  CS:ADR HIM OFF

/—запрещаем А20 MOV   АН,4

CALL   DWORD   PTR  CS:ADR_HIM_OFF

KON:

MOV AH,4CH.

INT 21H

ADR_HIM_OFF DW ? ADR_HIM_SEG DW ? CODE ENDS

END BEGIN

Puc. 22.4Простой пример использования НМЛ.

Программа на Рис. 22.4 копирует строку из сегмента данных в область НМЛ, а затем печатает строку уже из этой области.

В заключение обращаю внимание читателей на тот факт, что Windows 95 (и 98) эмулирует те виды памяти, которые мы сейчас разобрали для запускаемых из нее про­грамм, предназначенныхдля запуска в среде MS DOS.