Предыдущая глава УПРАВЛЕНИЕ ПАМЯТЬЮ И ЗАПУСК ПРОГРАММ Следующий раздел

18.1. Распределение памяти

Оперативная память – ресурс, требуемый для выполнения любой программы. В рассматриваемой ВС (DOS + i8086) объем адресуемого пространства ОП составляет 1 Мбайт. Только часть этого объема (640 К) соответствует реальной ОП (рис.63). Остальная часть адресов используется для работы с другими видами памяти (ПЗУ и видеопамять). Благодаря общему адресному пространству работа с этими видами памяти выполняется командами ЦП аналогично ОП, за исключением того, что в ПЗУ нельзя выполнять запись.

 

Рис.63. Распределение адресного пространства ОП

 

Как видно из рис.63, общий объем адресуемой памяти составляет не ровно 1 Мбайт, а немного больше (почти на 64К). Дело в том, что если поместить в регистр сегмента предельно большое значение (FFFFh), то за счет содержимого регистра-смещения можно превысить число FFFFFh, которое является номером старшего байта в первом мегабайте памяти. Предельная величина адреса получается суммированием чисел FFFF0h и FFFFh и равна 10FFEFh. Адреса за пределами 1 Мбайта соответствуют реальной ОП, которую DOS обычно использует для своих дополнительных  нужд. Основная часть ОП, занимаемой ОС, находится в начале адресного пространства.

Что касается прикладной программы, то ей может быть распределена вся память, оставшаяся от 640 К после размещения DOS. Распределение памяти программе, сделанное  до начала ее выполнения, называется статическим распределением памяти, а во время ее выполнения – динамическим распределением.

Статическое распределение памяти для exe- и com-программ выполняется операционной системой DOS различно. Несмотря на то, что для размещения com-программы требуется всего один блок памяти в 64 К, ОС распределяет ей всю память, свободную на момент создания программы. Для exe-программы DOS статически распределяет лишь первоначально необходимый объем ОП, определяемый длиной программы (включая PSP).

Что касается динамического распределения памяти, то может возникнуть вопрос о том, зачем оно вообще нужно в однопрограммной системе, каковой является DOS. Первой причиной его применения является то, что даже при выполнении единственной прикладной программы ее потребности в памяти для хранения своих данных могут превышать объем памяти, которая может быть предоставлена программе. Поэтому программа может выполнять освобождение областей памяти, занимаемых одними данными, для того, чтобы позже запрашивать области памяти для других своих данных.

 Вторая причина применения динамического распределения состоит в том, что DOS имеет зачатки мультипрограммных операционных систем, позволяя нескольким прикладным программам одновременно находиться в ОП. Это происходит, во-первых, тогда, когда одна прикладная программа запускается  по запросу другой прикладной программы. А во-вторых, прикладная программа может выполнять какие-то системные функции, дублируя или дополняя подпрограммы ОС, и поэтому должна находиться в памяти и во время выполнения других прикладных программ. Подобные запуски прикладных программ будут рассмотрены в следующих разделах, а пока лишь заметим, что для их реализации требуется, чтобы одна прикладная программа добровольно отказывалась бы от своей неиспользуемой памяти с целью обеспечения будущей загрузки другой программы (программ). 

Динамическое распределение памяти выполняется DOS по запросу самой прикладной программы. Для этого прикладная программа передает в ОС один из трех системных вызовов, рассматриваемых далее.

int 21h  (функция 48h) – выдать программе область памяти требуемого размера. Для передачи размера области, измеряемого в параграфах, используется регистр BX. В случае успеха DOS передает в регистре AX адрес-сегмент выделенной области памяти. Иначе – устанавливает флаг переноса FC=1.

Пример. Для создания своего буфера программа запрашивает область памяти длиной 500h параграфов:

            .   .   .   .   .   .   .   .

Bufseg        dw     0                       ; Адрес-сегмент новой области

            .   .   .   .   .   .   .   .

mov   ah, 48h                          ; Номер функции

mov   bx, 500h                        ; Размер области (в параграфах)

int     21h                               ; Запрос памяти

jc       Error                            ; Переход при ошибке

mov   Bufseg, ax                     ; Сохранить адрес-сегмент области

            .   .   .   .   .   .   .   .

int 21h  (функция 49h) – освободить область памяти, выделенную ранее динамически программе с помощью системного вызова “int 21h”  (функция 48h). Адрес-сегмент области программа передает в регистре ES. В случае ошибки DOS устанавливает флаг переноса FC=1.

Пример. Программа освобождает область памяти, адрес-сегмент которой находится в слове Bufseg:

            .   .   .   .   .   .   .   .

Bufseg        dw     0                      ; Адрес-сегмент области

            .   .   .   .   .   .   .   .

mov   ah, 49h                         ; Номер функции

mov   es, Bufseg                     ; Адрес-сегмент области

int     21h                              ; Освобождение памяти

jc       Error                          ; Переход при ошибке

            .   .   .   .   .   .   .   .

int 21h (функция 4ah) – изменить (увеличить или уменьшить) область памяти, принадлежащую программе. В регистре ES программа передает адрес-сегмент модифицируемой области, а в регистре BX – новый размер области памяти в параграфах. В случае ошибки DOS устанавливает флаг переноса FC=1.

Пример. Программа просит уменьшить размер области, выделенной ранее (в примере для функции 48h) до 200h параграфов ():

            .   .   .   .   .   .   .   .

Bufseg        dw     0                      ; Адрес-сегмент области

            .   .   .   .   .   .   .   .

mov   ah, 4ah                         ; Номер функции

mov   bx, 200h                       ; Новый размер области

mov   es, Bufseg                     ; Адрес-сегмент области

int     21h                               ; Изменить размер области

jc       Error                           ; Переход при ошибке

            .   .   .   .   .   .   .   .

Перейдем к рассмотрению принципов реализации динамического распределения памяти в DOS. Во-первых, вся ОП в системе разбита на области неодинаковой длины. Это разбиение со временем может изменяться, так как одни области могут разбиваться, а другие (соседние), наоборот, могут соединяться. Любая прикладная программа занимает минимум две области ОП. В одной из них находится сама программа (PSP, код, данные и стек), а во второй области находится блок окружения программы (размер этой области кратен 512 байтам). Число областей ОП, занимаемых программой, увеличивается в результате системных вызовов “int 21h” (функция 48h).

Во-вторых, каждая область памяти начинается с 16-байтового (один параграф)  блока управления области, который содержит:

1) в байте 0 – символ M, если область не последняя; Z – если область последняя в ОП;

2) в байтах 1 и 2 – адрес-сегмент PSP программы, являющейся владельцем данной области ОП. Если область свободна, то 0000h;

3) в байтах 3 и 4 – длина области в параграфах;

4) байты 5–15 – зарезервированы.

В-третьих, динамический запрос программы на получение дополнительной памяти DOS выполняет одним из трех способов:

1) последовательно просматривает блоки управления областей, двигаясь в сторону больших адресов, до тех пор, пока не встретится область памяти, не меньшая требуемой. Начальный адрес-сегмент этой области возвращается в программу, а ее излишек оформляется в новую свободную область. При отсутствии требуемой области устанавливается флаг CF;

2) последовательно просматриваются все свободные области памяти с целью нахождения минимальной области, которая не меньше требуемой;

3) отличается от способа 1 тем, что просмотр областей производится от больших адресов к меньшим.

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

Следует отметить, что при выполнении системных вызовов распределения памяти DOS «попутно» проверяет целостность всей цепочки блоков управления памятью. Поэтому нельзя портить содержимое этих блоков. Иначе ОС завершит работу системы, выдав соответствующее сообщение на экран.

В последующих разделах будут приведены примеры программ, содержащих системные вызовы для динамического распределения памяти.

 


Предыдущий раздел В начало Следующий раздел