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

         

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


Каждая процедура и функция 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 - селектор (адрес сегмента) сегмента динамических локальных данных библиотеки.


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