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

Конструкторы и деструкторы

Конструкторы и деструкторы используют те же соглашения о вы-

зовах, что и обычные методы, за тем исключением, что дополнитель-

ный параметр размером в слово, называемый параметром таблицы вир-

туальных методов, передается через стек непосредственно перед

параметром Self.

Для конструкторов параметр таблицы виртуальных методов со-

держит смещение таблицы виртуальных методов для запоминания поля

Self таблицы виртуального метода, чтобы инициализировать Self.

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

мического объекта с помощью расширенного синтаксиса стандартной

процедуры New, через параметр Self передается указатель nil. Это

заставляет конструктор размещать новый динамический объект, адрес

которого передается вызывающей программе через DX:AX при возврате

из конструктора. Если конструктор не может разместить объект, то

в DX:AX возвращается пустой указатель nil. (См. далее "Обнаруже-

ние ошибок конструктора").

Наконец, если конструктор вызывается с использованием уточ-

ненного идентификатора метода (т.е. идентификатора типа объекта,

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

таблицы виртуальных методов передается нулевое значение. Это яв-

ляется указанием конструктору на то, что ему не следует инициали-

зировать поле Self таблицы виртуальных методов. Для деструкторов

нулевое значение параметра таблицы виртуальных методов означает

обычный вызов, а ненулевое указывает, что деструктор был вызван с

использованием расширенного синтаксиса стандартной процедуры

Dispose. Это заставляет деструктор удалить Self непосредственно

перед возвратом (размер Self определяется из первого слова Self в

ТВМ).

Стандартный код входа и выхода

Каждая процедура и функция Borland Pascal начинается и за-

канчивается стандартным набором операторов, которые позволяют ак-

тивизировать и деактивизировать процедуру или функцию.

Стандартным входом служит следующая группа операторов:

PUSH BP ; сохранить регистр ВР

MOV BP,SP ; установить границы стека

SUB SP,LocalSize ; выделить память для локальных пере-

; менных

В этом примере LocalSize - это размер локальных переменных.

Инструкция SUВ присутствует только в том случае, когда LocalSize

не равно нулю. Если тип обращения к процедуре является ближним,

то параметры начинаются с BP+4, если для вызова процедуры исполь-

зуется дальний тип обращения, то они начинаются с BP+6.

Для программ DOS код входа и выхода для подпрограммы, ис-

пользующей дальнюю модель вызова, тот же, что и для подпрограммы

с ближним типом вызов, но для возврата из подпрограммы использу-

ется инструкция RETF. Это справедливо также для программы

Windows, cкомпилированной в состоянии {$W-}.

Примечание: Об использовании процедур входа и выхода в

DLL рассказывается в Главе 11 "Динамически компонуемые биб-

лиотеки".

Стандартной группой операторов выхода является:

MOV SP,BP ; освободить память, выделенную для

; локальных переменных

POP BP ; восстановить регистр ВР

RET ParamSize ; удалить параметры и выполнить возврат

; управления

Здесь РаrамSizе - это размер параметров. Инструкция RET яв-

ляется инструкцией ближнего или дальнего типа, в зависимости от

типа обращения к процедуре.

В состоянии {$W+} (по умолчанию) в подпрограмме, использую-

щей дальнюю модель вызова, код выхода и выхода выглядит следующим

образом:

INC BP ; указывает на кадр стека FAR

PUSH BP ; сохранить регистр ВР

MOV BP,SP ; установить кадр стека

PUSH DS ; сохранить DS

SUB SP,LocalSize ; выделить память для локальных переменных

.

.

.

MOV SP,BP ; освободить память, выделенную для

; локальных переменных

POP BP ; восстановить регистр ВР

DEC PB ; настроить BP

RETF ParamSize ; удалить параметры и выполнить возврат

; управления

Код входа и выхода для экспортируемой подпрограммы

(процедуры или функции, скомпилированной с директивой

компилятора export) выглядит следующим образом:

mov AXC,DS ; загрузить селектор DS в AX

nop ; дополнительное пространство для

; корректировок

inc BP ; указывает на дальний кадр стека

push BP ; сохранить BP

mov BP,SP ; установить кадр стека

push DS ; сохранить DS

mov DS,AX ; инициализация регистра DS

sub SP,LocalSize; распределении локальных переменных

. ; (если они имеются)

.

.

pop DI ; восстановить DI

pop SI ; восстановить SI

lea SP,[BP-2] ; освободить память, выделенную для

; локальных переменных

pop DS ; восстановить DS

pop BP ; восстановить BP

dec BP ; настроить регистр BP

retf ParamSize ; удаление параметров и возврат

; управления

Для всех моделей вызова, если подпрограмма не содержит ло-

кальных переменных, инструкции выделения и освобождения памяти

для локальных переменных можно опустить.

При работе в реальном режиме, чтобы различать ближний и

дальний кадр стека, Windows требует, чтобы все кадры стека (вклю-

чая кадры стека экспортируемых подпрограмм) сохраняли в слове по

адресу [BP+0] нечетное значение BP. Кроме того, Windows требует,

чтобы слово по адресу [BP-2] содержало селектор сегмента данных

вызывающей программы. Это объясняет использование инструкций INC

BP, PUSH DS и DEC BP (сгенерированных в состоянии {$W+}) на входе

и выходе для подпрограмм far и export.

Заметим, что использование {$W+} требуют только реальный

режим Windows. Если вы не поддерживаете реальный режим, укажите

{$W-}. Вы получите программу меньшего размера и некоторый выигрыш

в скорости.

При разработке программы защищенного режима Windows может

оказаться полезным использование состояния {$W+}. Некоторые

средства отладки, отличные от средств Borland, требуют этого для

корректной работы.

По умолчанию Borland Pascal автоматически генерирует эффек-

тивные системные вызовы для процедур и функций, экспортируемых

прикладной программой. При компоновке прикладной программы в сос-

тоянии {$K+} (по умолчанию) отладчик ищет в каждой экспортируемой

точке входа последовательность инструкций MOV AX,DS с последующей

инструкцией NOP, заменяя их на MOV AX.DS на MOV AX,SS. Это изме-

нение ослабляет требование использования при создании программ

системного вызова подпрограмм API Windows MakeProcInstanc и

FreeProcInstance (хотя это не возбраняется). Можно также вызывать

экспортируемые точки входа из самой прикладной программы.

В состоянии {$K-} при создании динамически компонуемой биб-

лиотеки компоновщик Borland Pascal не модифицирует код входа и

выхода экспортированной точки входа. Если подпрограмма системного

вызова в приложении должна вызываться из другой прикладной прог-

раммы, выбирать состояние {$K-} не следует.

При загрузке прикладной программы или динамически компонуе-

мой библиотеки Windows ищет в каждой экспортируемой точке входа

последовательность инструкций MOV AX,DS с последующей инструкцией

NOP. Для прикладной программы Windows изменяет первые три байта

на три инструкции NOP, чтобы подготовить подпрограмму для исполь-

зования ее функцией Windows MakeProcInstance. Для библиотек

Windows изменяет первые три байта в инструкции MOV AX,xxxx, где

xxxx - селектор (адрес сегмента) сегмента динамических локальных

данных библиотеки.

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