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

Параметры в стеке

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

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

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

Общие сведения

Стеком называется любой произвольно выбранный блок оперативной памяти, работа с которым производится по принципу "последнее записанное – первое считанное" (LIFOlast in first out). Иначе говоря, выражение "стек" характеризует не тип памяти, а способ работы с ней.

В процессе выполнения задачи в регистре ss хранится код сегмента оперативной памяти, в котором расположена область стека, а текущий адрес (смещение) верхушки стека в этом сегменте хранится в регистре SP, который называется указателем стека. Разрядность регистров зависит от режима работы микропроцессора: в реальном режиме они содержат по 16 разрядов, а в защищенном режиме по 32 разряда.

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

Для записи и чтения данных в режиме LIFO предназначены команды PUSH и POP, которые неоднократно использовались в примерах. Команда push предварительно уменьшает содержимое регистра sp, а затем записывает операнд в вычисленный адрес. Команда pop, наоборот, сначала считывает операнд, а затем увеличивает содержимое зр. В обоих случаях адрес, хранящийся в sp, изменяется на размер операнда, который может составлять 2 или 4 байта. Один байт записать в стек нельзя, команда push преобразует его в слово.

Кроме команд push и pop в режиме LIFO со стеком работают команды вызова обычных (сан) и прерывающих (int) подпрограмм и команды возврата из них (ret и iret).

Для непосредственного доступа к области стека выделен специальный регистр ВР. Он может использоваться в обычных командах (пересылки, сложения и пр.) в тех случаях, когда один их операндов расположен в области стека. Если операнд находится в регистре bp, то при его обработке микропроцессор, по умолчанию, выбирает в качестве сегментного регистра ss, a не DS, как обычно. В случае необходимости можно явно указать любой другой сегментный регистр.

Новое макроопределение

Перед обращением к подпрограмме в стек записываются ее параметры. Запись в стек обычно выполняет команда push. Для сокращения текста программы и придания ему большей наглядности можно использовать специальный макровызов. Текст соответствующего макроопределения приведен в примере В.4.

Пример В.4. Макроопределение для вызова подпрограмм.

@Invoke macro name, par; заголовок макроопределения
irp r, <par>; начало оператора повторения
push r; заготовка повторяемой команды
endm; конец оператора повторения
call name; заготовка команды вызова подпрограммы
endm; конец текста макроопределения

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

Если макроопределение примера В.4 включено в текст основной задачи, то для его использования в нужном месте указывается следующий макровызов:

@Invoke имя_процедуры <список_параметров>

Имя процедуры может быть как внешним, так и внутренним. Список параметров обязательно заключается в угловые скобки, а параметры отделяются друг от друга запятыми, после которых допустим пробел. Форма записи параметров стандартная для команды push. Пример использования макровызова приведен в конце данного раздела.

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