Руководство по языку B.Pascal 7

Вложенные процедуры и функции


Процедура или функция считается вложенной, когда она описы- вается внутри другой процедуры или функции. По умолчанию вложен- ные процедуры и функции всегда используют ближний тип вызова (NEAR), поскольку они доступны только внутри определенной проце- дуры или функции в том же сегменте кода. Однако в оверлейных за- дачах обычно для того, чтобы обеспечить для всех процедур и функ- ций дальний тип вызова (FAR), используется директива {$F+}.

При вызове вложенной процедуры или функции компилятор непос- редственно перед инструкцией CALL генерирует инструкцию PUSH BP, фактически передавая регистр BP вызывающей программы в качестве дополнительного параметра. После того, как вызываемая процедура установит свой собственный регистр BP, регистр ВР вызывающей про- цедуры доступен, как слово, сохраненное в [BP+4] или в [BP+6] (если процедура имеет дальний тип вызова). Используя связь через [BP+4] и [BP+6], вызываемая процедура может получить доступ к ло- кальным переменным в границах стека вызывающей процедуры. Следую- щий пример показывает, как можно получить доступ к локальным пе- ременным из оператора inline во вложенной процедуре:

procedure A; near; var IntA: integer;

procedure B; far; var IntB: integer;

procedure C; near; var IntC: integer; begin inline( $8B/$46/<IntC>/ { MOV AX,[BP+IntC] ;AX = IntC } $8B/$5E/$04/ { MOV BX,[BP+4] ;BX = стек В } $36/$8b/$47/<IntB>/ { MOV AX,SS:[BX+IntB] ;AX = IntB } $8B/$5E/$04/ { MOV BX,[BP+4] ;BX = стек B } $36/8B/$5F/$06/ { MOV BX,SS:[BX+6] ;BX = стек A } $36/$8B/$47/<IntA>); { MOV AX,SS:[BX+IntA] ;AX =IntA } end;

begin C end;

begin B end;

Примечание: Вложенные процедуры и функции нельзя описы- вать с помощью директивы external, и они не могут иметь па- раметры процедурного типа.

Примечание: Блок inline в приведенном примере можно записать также в виде:

begin asm MOV AX,[BP+IntC] { AX = IntC } MOV BX,[BP+4] { BX = стек В } MOV AX,SS:[BX+IntB] { AX = IntB } MOV BX,[BP+4] { BX = кадр стек B } MOV BX,SS:[BX+6] { BX = кадр стек A } MOV AX,SS:[BX+IntA] { AX =IntA } end; end;



Содержание раздела