Работа с именами сегментов
Работа с именами сегментов
Макроассемблер рассматривает имя сегмента как константу (а не как переменную), ее прямая пересылка в сегментный регистр невозможна, поэтому приходится использовать регистр-посредник. Например, в большинстве случаев в начале выполнения задачи надо определить содержимое сегментного регистра DS, поместив в него код сегмента данных. Это можно сделать с помощью двух следующих команд:
start: mov ax, data ; ax = код сегмента данных mov ds, ax ; ds = ax
Этот пример составлен исходя из предположения, что сегмент данных описан так, как приведено в примере Б.1. Если же он описан, как в примере Б.2, то в первой команде надо изменить имя data на _data или @data.
Макроассемблер позволяет определить код сегмента тремя разными способами: указать его явно в виде числа, указать имя сегмента или указать имя метки, расположенной в нужном сегменте. В последнем случае перед именем метки помещается оператор seg. Следующие три команды иллюстрируют сказанное:
mov ax, 0400h ; указание конкретного числового значения
mov ax, job ; явное указание имени сегмента
mov ax, seg buf ; косвенная ссылка на сегмент по имени метки
Команды первого типа нужны при обращении к сегментам, расположенным вне тела программы, например к области данных BIOS.
Команды второго типа применяются при работе с сегментами, описанными в тексте программы. Точное значение таких сегментов заранее неизвестно, его вычисляет DOS при загрузке программы в память для выполнения.
Команды третьего типа полезны в тех случаях, когда метка является внешним именем, не описанным в программе, и нужно узнать, какому сегменту она принадлежит.
После того, как с помощью одной из этих команд значение сегмента окажется в регистре ах, оно копируется в нужный сегментный регистр командой пересылки, как это было показано выше на примере определения содержимого регистра ds.
Резервирование пространства памяти. Большинство графических задач нуждается в определенном пространстве ОЗУ для размещения буферов различного назначения. В простейшем случае для резервирования требуемого пространства памяти в текст программы включаются дополнительные сегменты.
Это можно сделать, например, так:
Job Segment ; начало сегмента
buffer db 65536 dup (?) ; директива резервирует 65536 байтов
Job Ends ; конец сегмента
В приведенном примере сегмент становится частью тела задачи и увеличивает его размер на соответствующее количество байтов. Поэтому такой способ распределения пространства ОЗУ является вспомогательным и применять его можно только в порядке исключения.
Более гибкий и универсальный вариант заключается в том, что для размещения буферов различного назначения пространство оперативной памяти не резервируется в исходном тексте программы, а распределяется в процессе выполнения задачи.