ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



 

Часть 20

                             ГЛАВА 18.

                         ВОПРОСЫ КОНТРОЛЯ.

     Эта глава детально описывает различные способы, которыми Turbo
Pascal реализует  управление программой.  Она включает соглашения о
вызовах процедуры выхода, обработку прерываний и обработку ошибок.


                       Соглашения о вызовах.

     Параметры передаются  в  процедуры  и  функции через стек.  До
вызова процедуры или функции параметры помещаются в стек  в порядке
их  объявления.  Перед  возвратом процедура или функция удаляет все
параметры из стека.
     Этот код для процедуры или функции будет выглядеть:

     Push Param1
     Push Param2
     .
     .
     .
     Push ParamX
     Call ProcOrFunc

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


                       Изменяемые параметры.

     Изменяемый параметр (var параметр) всегда передается по ссылке
- указатель  указывает  на   действительное   положение   параметра
(адрес).


                      Неизменяемые параметры.

     Неизменяемый параметр передается по ссылке или по  значению  в
зависимости  от  типа и размера параметра.  Если значение параметра
занимает 1,  2 или 4 байта,  то значение помещается в стек. Иначе в
стек помещается  указатель  на  значение,  и  процедура или функция
затем копирует это значение в локальную область памяти.

     Примечание: 8086 не поддерживает однобайтовые  инструкции Push
и Pop, поэтому однобайтовые параметры всегда помещаются в стек, как
слова.  Младший байт слова содержит значение,  а  старший  байт  не
используется (не определен).

     Целый тип  или  параметр,  передаваемый  как  байт,  слово или
двойное слово всегда использует такой  же  формат,  как  переменная
целого типа. (Для двойного слова старшее слово помещается в стек до
младшего слова так, что младшее слово имеет младший адрес).
     Параметр символьного типа передается как беззнаковый байт.
     Параметр логического  типа  передается как байт со значением 0
или 1.
     Параметр перечислимого типа передается как  беззнаковый  байт,
если   перечисление   имеет  256  или  меньше  значений,  иначе  он
передается как беззнаковое слово.
     Параметр типа  Real  передается  как  6 байт в стек и является
исключением из правил,  что только 1,  2 или 4-x байтовые  значения
передаются прямо через стек.
     Параметр вещественного типа (Real,  Single, Double, Extended и
Comp)  передается  как  4,  6,  8  или  10  байт  в стек и является
исключением из правил,  что только 1,  2 или  4  байтовые  значения
передаются прямо в стек.

     Примечание: Turbo  Pascal  версии 4.0 передавал параметры типа
8087  (Ringle,  Double,  Extended  и  Comp)  во   внутренний   стек
математического  сопроцессора  8087.  Для  совместимости  с другими
языками и  предотвращения  переполнения  стека  8087,  эта   версия
использует  стек  8086.

     Параметр типа Рointer передается как двойное слово (сегментная
часть передается до части смещения так, что часть смещения занимает
младшие адреса).
     Параметр типа String передается, как указатель на значение.
     Параметр типа   множество   передается,   как   указатель   на
"неупакованное" множество, которое занимает 32 байта.
     Массивы и  записи  длиной 1,  2 или 4 байта передаются прямо в
стек. Другие массивы и записи передаются как указатель на значение.


                        Результаты функции.

     Результаты функции порядкового типа (Integer,  Char, Boolean и
перечислимый) передаются в регистрах процессора: байты передаются в
AL,  слова  передаются  в  AX  и  двойные  слова передаются в DX:AX
(старшее слово в DX, младшее слово в AX).
     Результат функции типа Real возвращается в регистрах DX:BX:AX.
(Старшее слово в DX, среднее слово в BX, младшее слово в AX).
     Результаты функций типа 8087 (Single, Double, Extended и Comp)
передаются в регистр вершины стека 8087 (ST(0)).
     Результат функции  типа Pointer передается в DX:AX (сегментная
часть в DX, часть смещения в AX).
     Для результатов  функций  типа  String,  вызывающая  программа
помещает указатель на временную область памяти до  помещения  любых
параметров, и функция возвращает строковое значение в эту временную
память. Функция не должна удалять указатель.


              Ближние и дальние вызовы (NEAR и FAR).

     Процессор 8086  поддерживает  два  типа  инструкций  вызова  и
возврата: NEAR и FAR. NEAR (ближняя) инструкция передает управление
в другую  точку  внутри того же кодового сегмента,  а FAR (дальняя)
инструкция позволяет изменить кодовый сегмент.
     Инструкция NEAR  CALL  помещает  16-ти  битовый адрес возврата
(только смещение) в стек,  а  инструкция  FAR  CALL  помещает  32-х
битовый адрес  возврата  (и  сегмент  и смещение).  Соответствующие
инструкции RET выталкивают из стека только смещение или  и смещение
и сегмент.
     Turbo Pascal   на   основе    объявления    процедуры    будет
автоматически   выбирать   правильную   модель  вызова.  Процедуры,
объявленные в секции interfaсe  модуля,  будут  FAR,  так  как  они
вызываются  из других модулей.  Процедуры,  объявленные в программе
или в секции implementation модуля,  будут NEAR,  так как они могут
быть вызваны только внутри программы или модуля.
     Для некоторых специальных целей  может  требоваться  процедура
типа  FAR.  Например,  в  программах  с  оверлеями  все процедуры и
функции должны быть FAR;  кроме того,  если процедура  или  функция
присваивается  процедурной  переменной,  она также должна быть FAR.
Директива компилятора $F используется  для  отмены  автоматического
выбора    модели   вызова   компилятором.   Процедуры   и   функции
откомпилированные в состоянии {$F+} всегда FAR; в состоянии {$F-} -
Turbo Pascal автоматически выбирает правильную модель. Состояние по
умолчанию {$F-}.


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

     Процедура или   функция   называется   вложенной,   когда  она
объявлена  внутри  другой  процедуры  или  функции.  По   умолчанию
вложенные процедуры и функции всегда используют модель вызова NEAR,
поскольку они "видимы" только  внутри  определенной  процедуры  или
функции, находящейся в том же кодовом сегменте. Однако в оверлейных
программах  директива  {$F+}  используется  для  установления  всех
процедур и функций в FAR, включая и вложенные.
     Когда вызывается вложенная процедура или  функция,  компилятор
генерирует инструкцию PUSH BP перед CALL, в результате передавая BP
вызывающей  процедуре,  как  дополнительный   параметр.   Поскольку
вызванная   процедура  устанавливает  свой  собственный  BP,  к  BP
вызывающей процедуры можно обратиться как к  слову,  хранящемуся  в
[BP  + 4] или [BP + 6],  если процедура FAR.  Используя связь через
[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/




Яндекс цитирования