Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
BorlandPascal.doc
Скачиваний:
55
Добавлен:
17.03.2015
Размер:
2.83 Mб
Скачать

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

Процедура или функция считается вложенной, когда она описы-

вается внутри другой процедуры или функции. По умолчанию вложен-

ные процедуры и функции всегда используют ближний тип вызова

(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;

Соглашения о вызовах методов

Методы используют те же соглашения о вызовах, что и обычные

процедуры и функции, за тем исключением, что каждый метод имеет

неявный дополнительный параметр Self, который соответствует пара-

метру-переменной того же типа, что и объектный тип данного мето-

да. Параметр Self всегда передается последним и всегда имеет фор-

му 32-разрядного указателя на экземпляр, из которого вызывается

метод. Например, если переменная PP имеет тип PPoint, как опреде-

лено выше, то вызов PP^.MoveTo (10, 20) кодируется следующим об-

разом:

mov ax, 10 ; загрузить 10 в AX

push ax ; передать PX как параметр

mov ax, 20 ; загрузить 20 в AX

push ax ; передать PY как параметр

les di, PP ; загрузить PP в ES:DI

push es ; передать, как параметр Self

push di

mov di, es:[di + 6] ; извлечь смещение ТВМ из поля ТВМ

call DWORD PTR [di + 16] ; вызвать запись ТВМ для MoveTo

Во время возврата метод должен удалить параметр Self из сте-

ка точно так же, как он удаляет обычные параметры.

Методы всегда используют дальний тип вызова, независимо от

состояния директивы $F компилятора.

Соседние файлы в предмете Программирование на Pascal