Директивы описания процедур
Выполняемые команды, которые располагаются в сегменте кода, часто оформляются в виде одной или нескольких процедур. Обычно выделяется главная процедура, которая служит для выполнения основных действий программы и определения точки входа в программу, и подпрограммы, которые предназначены для многократного выполнения часто повторяющихся действий.
Синтаксическое описание любой процедуры на языке ассемблера осуществляется директивами PROC (начало процедуры) и ENDP (конец процедуры) и представляет собой конструкцию, показанную на рис.5.3.
Рис. 5.3. Директивы описания процедур
Имя процедуры должно обязательно присутствовать, быть уникальным и удовлетворять соглашениям по именам на ассемблере. Расстояние может принимать два значения NEAR (по умолчанию) и FAR и характеризует возможность обращения к процедуре из другого сегмента кода. Команда RET завершает выполнение процедуры и возвращает управление в DOS или в исходную программу.
Процедуры типа NEAR вызываются с помощью вызова ближнего типа и содержат ближний возврат управления, то есть они могут вызываться только из того сегмента, в котором они были определены. Вызов ближнего типа заносит адрес возврата в стек (адрес возврата определяется смещением точки возврата относительно начала сегмента кода, то есть это значение регистра IP) и устанавливает указатель команд (IP) в значение смещения начала вызываемой процедуры. Когда процессор обнаруживает возврат ближнего типа (команду RET), он извлекает из стека адрес возврата и снова устанавливает его в регистр IP. Сегмент кода не изменяется и, следовательно, регистр CS не модифицируется.
Процедуры типа FAR вызываются с помощью вызова дальнего типа и содержат возврат дальнего типа, и они могут вызываться вне сегмента, в котором они были определены. Вызов FAR заносит в стек адрес возврата в виде сегмента и смещения (точка возврата определяется парой регистров CS:IP), а затем в пару регистров CS:IP устанавливается адрес вызываемой процедуры. Когда процессор обнаруживает возврат дальнего типа (команду RET), он извлекает из стека адреса возврата и устанавливает их обратно в пару регистров CS:IP.
Очень важно, чтобы перед выполнением команды RET стек возвращался в исходное состояние (какое было до вызова процедуры). В противном случае при выполнении команды RET, из стека будет извлечен неправильный адрес возврата.