На главную
Подписка
Новости










Главная / MS-DOS / MS-DOS. РУКОВОДСТВО РАЗРАБОТЧИКА / Глава 2 / Интерфейс с языками высокого уровня Сделать домашней страницей Добавить в избранное Написать писмо

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Интерфейс с языками высокого уровня

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


Имеется три главных области, относящихся к связи программ на языке Ассемблер с программами на языке высокого уровня. Это - согласование имен между двумя модулями; обработка любых специальных установок, которые могут требовать язык программирования и компилятор языка; настройка модулей языка Ассемблер для надлежащей последовательности вызова и инструмента передачи параметров, используемых компилятором конкретного языка высокого уровня.


В прошлом, для языков высокого уровня было достаточно мало правил регулировки соглашений о присвоении имен и последовательностей вызова. Сегодня ситуация во многом изменилась, т.к. многие компиляторы следуют стандартам Американского национального института стандартов (ANSI). В связи с широким использованием компиляторов языков высокого уровня фирмы "Майкрософт" и в связи с тем, что они придерживаются стандартов ANSI, оказалось возможным выбрать компиляторы фирмы "Майкрософт" с языков программирования: Бэйсик, Си, Фортран и Паскаль для иллюстрации соглашений вызова подпрограмм.


Соглашения о связях для языка Си фирмы "Майкрософт"


Соглашения о связях, проиллюстрированные в листинге 2-8, представляют типичную программу на языке программирования Си. Если бы программу Example перетранслировать на язык Си, то ее начальные предложения были бы похожи на следующие:



              void Example (Param1, Param2, Param3)
                   int Param1, Param2, Param3 ;
                   {
                   int LocIndx ;
                   char LocChar [14] ;
                   int LocWord ;
                   ...   ...

В языке Си все подпрограммы являются также функциями; любая подпрограмма может возвращать значение в вызывающую программу. В связи с тем, что приведенная функция не возвращает значение, она объявлена как пустая функция (void).


Язык программирования Си обеспечивает использование автоматических (automatic) переменных для запоминания локальных данных. Заметим, однако, что отсутствует стандарт, предписывающий порядок размещения в стеке локальных переменных.


В листинге 2-8, рис. 2-1 и в приведенном выше фрагменте программы показано как язык Си помещает свои аргументы в порядке, обратном их объявлению. Целью этого способа является то, что если передается переменное количество параметров, то вызываемая программа может всегда найти самый левый параметр на фиксированной позиции в стеке. Параметр Param1 будет всегда размещаться в [BP + 4], независимо от того, какое количество параметров было в действительности передано. Программы на языке Си, допускающие использование этой особенности, обычно используют самый левый или первый параметр для передачи общего количества параметров, передаваемых в вызываемую программу. При этом способе вызываемая программа может определить сколько параметров ей необходимо прочитать.


Другой особенностью, отмечаемой в языке Си, является то, что параметры почти всегда передаются по значению. Если вызвать про цедуру Example (пример) с переменной FOO, то содержимое переменной FOO будет помещено в стек. Вызываемая программа, таким образом, работает с копией переданной переменной, а не с ней самой. Исключение этого способа состоит в том, что массив обычно передается по адресу. (В стандартном языке Си идентификатором массива является его адрес, так что это кажущееся исключение в действительности согласуется с синтаксисом языка Си). Однако, язык Си позволяет программисту передавать адрес любой переменной, если потребуется.


Компилятор языка Си фирмы "Майкрософт" поддерживает богатейшую среду программирования, позволяющую опытному программисту полное управление памятью, используемой модулем. В приведенном примере представлена среда программирования языка Си по умолчанию, состоящая из вызова программы near (близкий) и ссылки near на данные.


Вопреки уже сделанным попыткам, не будем заменять версию процедуры Example (пример) программой на языке Си. Одно из препятствий, которое необходимо преодолеть, состоит в согласовании имен, используемых между вызывающей программой на языке Си и вызываемой программой на языке Ассемблер. Проблема заключается в том, что компилятор языка Си ставит префикс "подчеркивание" (_) перед всеми именами. Когда компилятор генерирует вызов программы Example (пример), он реально предполагает, что именем программы пункта назначения является "_Example". Возможно, что эта терминология разработана для предотвращения коллизий между пространством имени компилятора и пространством имени Ассемблера. Если и вызывающая и вызываемая программы написаны на языке Си, то компилятор транслирует обе ссылки и поэтому нет никаких неприятностей. Когда одна из ссылок на языке Ассемблер, то необходимо выполнить трансляцию самим. Эта трансляция применяется для выдачи имен переменных глобальных данных также успешно, как и программных меток.


Следует отметить два существенных момента:


- в языке программирования Си имена ограничены 8 символами;


- все имена в языке программирования Си чувствительны к регистру.


В языке программирования Си "Example" и "example" это два разных имени. Программы на языке программирования Ассемблер должны ассемблироваться с переключателем /mx для предохранения от используемого регистра любого имени.



                                                       Таблица 2-1
                 Соглашения о связях для языка Си фирмы "Майкрософт"
         _______________________________________________________________
                                   |
              Соглашение           |                 Описание
         __________________________|____________________________________
                                   |
          Ссылка на программу      | Near (близкие) или far (далекие)
          Ссылки на данные         | Near (близкие) или far (далекие)
          Стек очищается           | вызывающей программой
          Параметры передаются в   | обратном порядке
          Параметры передаются по  | значению
          Значения возвращаются в  | регистре AX или DX:AX
          Длина имени              | 8 символов
          Всем именам предшествует | символ "подчеркивание" (_)
         __________________________|____________________________________

Последним требованием к языку программирования Си является возможность вызова программ на языке Ассемблер. Это требование обеспечивается тем, что на языке Ассемблер функция должна быть объявлена как public (общая), а на языке Си - как extern (внешняя). Краткие сведения о соглашениях о связях для языка программирования Си фирмы "Майкрософт" приведены в таблице 2-1.


Соглашения о связях для языка Паскаль фирмы "Майкрософт"


Если листинг 2-8 приближается к синтаксису вызова для языка Си фирмы "Майкрософт", то соглашения о связях для компилятора языка Паскаль фирмы "Майкрософт" лучше выражаются с помощью примера, приведенного в листинге 2-4. Вызов на Паскале эквивалентен вызову процедуры myproc (моя процедура), закодированному следующим образом:



               procedure MyProc (Param1, Param2, Param3 : integer) ;
               begin
                ...

Главное отличие между языками Си и Паскаль состоит в том, что Паскаль выполняет гораздо больше строгих проверок. Эти проверки гарантируют: что при вызове передается правильное количество и типы параметров; что значения функции используются способом, соответствующим их типу и т.д. Таким образом, в отличие от языка Си, в языке Паскаль программа должна быть объявлена либо процедурой (подпрограмма, которая не возвращает значения), либо функцией.


Язык Паскаль также обеспечивает использование автоматических переменных для памяти локальных данных. Как и в языке Си, в языке Паскаль нет стандартных решений о назначении порядка локальных переменных в стеке. Также, как и в языке Си, в Паскале память для локальных переменных распределяется при вершине стека на входе в вызываемую программу. Если процедура MyProc использует локальные переменные LocIndx, LocChar и LocWord, то они должны будут ссылаться так, как показано в структуре StackFrame листинга 2-8. Паскаль эквивалентен программе, похожей на ниже приведенную:



               procedure MyProc (Param1, Param2, Param3 : integer) ;
               var
                   LocIndx, LocWord : integer ;
                   LocChar [1..14] : character ;
               begin
                ...

Из листинга 2-4 можно увидеть, что в отличие от языка Си, язык Паскаль помещает свои аргументы в порядке, в котором они объявляются, слева направо. Причина, по которой этот способ возможен, состоит в том, что компилятор языка Паскаль гарантирует, что все обращения, выдаваемые программой, обеспечивают правильное количество и типы аргументов. Язык Паскаль просто не позволяет передавать переменное количество параметров, поэтому порядок передачи, используемый в языке Си, не требуется в языке Паскаль.


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


Другим сходством с языком Си является то, что язык Паскаль обычно передает свои переменные по значению, однако, если требуется, то переменные можно передавать по адресу, используя описание var (переменная).



                                                         Таблица 2-2
                Соглашения о связях языка Паскаль фирмы "Майкрософт"
         ________________________________________________________________
                                       |
                  Соглашение           |           Описание
         ______________________________|_________________________________
                                       |
          Программные ссылки           | Far (далекие)
          Ссылки на данные             | Far (далекие)
          Стек очищается               | вызываемой программой ( RET N)
          Параметры передаются в       | порядке объявления
          Параметры передаются по      | значению
          Значения возвращаются в      | регистре AX или DX:AX
          Длина имени                  | 8 символов
          Все имена являются           | нечувствительными к регистру
         ______________________________|_________________________________

В отличие от языка Си, компилятор языка Паскаль фирмы "Майкрософт" использует модуль памяти LARGE (большой), предполагающий вызовы far (далекий) и ссылки по памяти far (далекие). Также, в отличие от Языка Си, язык Паскаль распознает имена на любом регистре, несмотря на то, что функция языка Ассемблер должна быть еще объявлена как public (общая), а ссылки языка Паскаль должны быть объявлены как extern (внешние). Краткие сведения о соглашениях о связях в языке Паскаль фирмы "Майкрософт" приведены в таблице 2-2.


Соглашения о связях языков Фортран и Бэйсик фирмы "Майкрософт"


Стандартные компиляторы языков программирования Бэйсик и Фортран фирмы "Майкрософт" очень похожи на компилятор языка Паскаль фирмы "Майкрософт". Таблица 2-3 справедливо показывает, как много имеется сходства при стандартных вызовах. Однако, имеются и отличия. Главным отличием от соглашений о связях языка Паскаль состоит в том, что и Бэйсик и Фортран передают свои аргументы по ссылкам. Так как эти языки программирования передают адреса переменных, любые манипуляции переменными, выполняемые вызываемой программой, также изменяют значения переменных в вызывающей программе.


В действительности, сходство между всеми четырьмя интерфейсами означает, что как легко написать подпрограмму на языке Ассемблер для Бэйсика и Фортрана, также легко и для Паскаля или языка Си. Однако, в программах языков Бэйсик и Фортран для установки правильного интерфейса требуются большие усилия.


Эквивалентом предложения extern (внешний) в языке Бэйсик является предложение DECLARE (объявить), в то время как в языке Фортран требуется предложение INTERFACE (интерфейс). Каждое из этих предложений информирует соответствующий компилятор о том, что имя соответствующей программы должно находиться вне текущего модуля. Для информирования компилятора о том, как сформатировать и сгенерировать правильный вызов, могут потребоваться дополнительные параметры. Соглашения о связях для языков Бэйсик и Фортран фирмы "Майкрософт" приведены в таблице 2-3.



                                                         Таблица 2-3
                  Соглашения о связях для языков Бэйсик и Фортран
                                 фирмы "Майкрософт"
          ___________________________________________________________
         |                      |                 |                  |
         |     Соглашение       |    Бэйсик       |   Фортран        |
         |______________________|_________________|__________________|
         |                      |                 |                  |
         |Ссылки на программы   |Far (далекий)    |Far (далекий)     |
         |Ссылки на данные      |Far (далекий)    |Far (далекий)     |
         |Стек очищается        |     вызываемой программой (RET N)  |
         |Параметры передаются в|         в порядке объявления       |
         |Параметры передаются  |по адресу Far(да-|по адресам Near   |
         |                      |лекий)           |(близкий)/Far (да-|
         |                      |                 |лекий)            |
         |Значения возвращаются |       регистре AX или DX:AX        |
         |Длина имени           |40 символов      |6 символов        |
         |Все имена представлены|на верхнем ре-   |нечувствительны   |
         |                      |гистре           |к регистру        |
         |______________________|_________________|__________________|

Модель сегмента фирмы "Майкрософт"


Версия 5.0 макроассемблера MASM фирмы "Майкрософт" дает возможность программисту быстро указывать надлежащие имена сегментов и устанавливать их для данного языка программирования с помощью директивы MODEL. Даже без версии 5.0 установка надлежащего шаблона языка Ассемблер относительно проста. Все четыре языка программирования используют одинаковые первичные имена сегментов. Имя кодового сегмента "_TEXT", а имя сегмента данных "_DATA". Для отдельных интерфейсов могут потребоваться дополнительные сегменты, и многие модели компиляторов фирмы "Майкрософт" требуют, чтобы стек помещался бы в сегмент данных. Однако, простой программе на языке Ассемблер не нужно беспокоиться об этом, так как она может просто отключить функционирование стека в вызывающей программе и все необходимые установки будет поддерживать главная подпрограмма языка высокого уровня.


НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Hosted by uCoz