Иллюстрированный самоучитель по SVGA

Работа процедур со стеком

В первом варианте примера В.6 показано, как резервируется пространство размером N байтов с помощью обычных команд. Начиная с модели Intel 80286, у микропроцессоров появилась специальная команда enter. Она сохраняет в стеке содержимое регистра bp, копирует в bp адрес верхушки стека и уменьшает на N содержимое sp, т. е. по результату эквивалентна трем командам варианта 1. При использовании во внешних процедурах второй параметр команды enter равен нулю.

Важно
Ни при каких обстоятельствах значение указателя стека не может быть нечетным числом. Поэтому количество байтов, отводимых для размещения промежуточных переменных, обязательно должно быть четным. Однако это не означает, что в пространстве стека нельзя размещать байты и работать с ними
.

После выполнения любого из вариантов примера В.6 регистр bp используется для прямого доступа к параметрам и промежуточным переменным. Параметры расположены выше, а промежуточные переменные – ниже находящейся в bp точки отсчета. Обозначим смещение параметра или переменной как хх. В таком случае, при обращении к параметрам содержимое в bp увеличивается на величину смещения ([bp+хх]), а при обращении к промежуточным переменным оно уменьшается на величину смещения ([bp-хх]).

Прежде чем использовать переменные в командах, надо вычислить смещение каждой из них относительно регистра bp. Оно зависит от размеров предыдущих и данной переменной и не может быть равно нулю. Например, первая по порядку переменная может быть байтом, словом или двойным словом, ее адрес будет соответственно равен [bp-i], [bp-2] или [bp-4].

Имена параметров и переменных

Запись адреса в явном виде вполне корректна, но не наглядна. Для того чтобы текст подпрограммы был более понятен, при визуальном анализе лучше использовать имена.

Особенность данного случая в том, что переменные и параметры распределяются не статическим, а динамическим способом. Это не позволяет использовать для их описания обычные директивы db, dw и пр. Вместо этого используется директива EQU (эквивалентно). Перед ней указывается имя параметра или переменной, а после нее описание адреса и размера.

Предположим, что внешней подпрограмме передаются два параметра, каждый из которых имеет размер слова. Один их них задает ширину строки на экране в точках, а второй – количество строк на экране. В Главе 2 для обозначения этих величин были введены имена Horsize и versize. Для присвоения этих имен параметрам в текст модуля подпрограммы надо включить две следующие директивы:

Horsize EQU word ptr [bp + 6]; количество точек в строке Versize EQU
word ptr [bp + 8]; количество строк на экране

В этом примере предполагается, что перед вызовом внешней процедуры в стек сначала было записано значение параметра versize, а затем Horsize, например, так:

@Invoke имя_подпрограммы <Versize, Horsize>

Только в таком случае описание параметров соответствует их реальному расположению в стеке.

Обычно директивы EQU размещаются в начале тела модуля, вне сегмента (или вне сегментов). Имена, присвоенные в подпрограмме, являются локальными, поэтому вполне допустимо их совпадение с именами, описанными в основной программе или в других подпрограммах.

При указанном описании параметров для вычисления количества точек на экране в тексте подпрограммы выполняются следующие две команды:

mov ах, Horsize; ах = количество точек в строке mui Versize
; dx:ax = Horsize * Versize

Описание промежуточных переменных отличается от описания параметров только указанием отрицательного смещения относительно bp, пример:

Address EQO word ptr [bp – 2]; описание переменной Address

Следует отметить, что последовательность директив EQU является своеобразным описанием формальных параметров. Если такие директивы включены в текст модуля, то по его распечатке можно определить тип и последовательность указания параметров при вызове процедуры.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.