 |
Какие проблемы могут возникнуть при использовании Пас-
каль-соглашения по вызову?
Во-первых, оно не так сильно, как Си-соглашение по вызову.
Вы не можете передать переменное число параметров (что возможно в
случае Си-соглашения), т.к. вызванная подпрограмма должна знать,
сколько параметров заносится в стек и, соответственно, извлекает-
ся из него. Передача слишком малого или слишком большого коли-
чества параметров будет приводить к серьезным трудностям, в то
время как при Си-соглашении это не даст нежелательного эффекта
(за исключением, возможно, неверных ответов).
Во-вторых, если вы используете -р опцию транслятора, то вы
должны обязательно включить файлы заголовков для стандартных
Си-функций, которые вы вызываете. Это необходимо потому, что если
вы этого не сделаете, Турбо Си будет использовать Паскаль-согла-
шение для вызова каждой из этих функций, и ваша программа навер-
няка потерпит крах, потому что:
1) параметры будут в неверном порядке;
- 377,378 -
2) ничем не будет очищаться стек.
Файлы заголовков объявляют каждую из таких функций как
cdecl, поэтому, если вы включете их, транслятор увидит это и бу-
дет использовать Си-соглашение по стеку. Однако, т.к. идентифика-
торы cdecl дополняются символом подчеркивания, в отличие от иден-
тификаторов Pascal, то при компоновке вы получите множество
ошибок, если не установите режим Generate undebars "Off". Потом у
вас будут большие неприятности.
Заключение: если вы собираетесь использовать Паскаль-согла-
шение по вызову в программе Турбо Си, то убедитесь, что каждая
функция явно объявлена как cdecl или pascal. Это очень полезно в
случае использования опции компиляции о требовании наличия прото-
типа, т.к. в этом случае вы можете быть уверены, что каждая функ-
ция вызывается строго в соответствии с ее прототипом.
Интерфейс с языком ассемблера
-----------------------------------------------------------------
Теперь вы знаете, как работает каждое соглашение по вызову и
что в этом случае делает компилятор Турбо Си. Что же вам необхо-
димо делать в вызываемой подпрограмме? Расмотрим это на примере
написанной на ассемблере подпрограммы, которую можно вызывать из
Турбо Си.
Замечание: в этом разделе мы подразумеваем, что вы знаете,
как писать программы на языке ассемблера для 8086 и как опреде-
лять сегменты, константы данных и т.п. Если вы не знакомы с этими
вопросами, то можете ознакомиться с ними в Turbo Assembler
Reference Guide.
Порядок вызова ассемблера из Турбо Си
-----------------------------------------------------------------
Вы можете написать подпрограммы на языке ассемблера в виде
модулей и скомпоновать их с вашими программами на Си. Однако име-
- 379,380 -
ются определенные соглашения, которым вы должны следовать:
1) убедиться, что компоновщик может получить необходимую ин-
формацию;
2) убедиться, что формат файла согласуется с типом модели
памяти, используемой в вашей программе на Си.
Ниже приведена общая схема программы:
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
Идентификатор Имя Имя файла
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:, DS:
<........... code segment ............>
ENDS
GROUP _DATA,_BSS
SEGMENT WORD PUBLIC 'DATA'
<..... initialized data segment .....>
ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
<..... initialized data segment .....>
_BSS ENDS
END
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
Индентификаторы , и в этой схеме имеют
- 381,382 -
специальные заменители, зависяшие от используемой модели памяти.
Таблица 12.5 показывает, какие надо использовать в каждой модели.
Filename в этой таблице - имя модуля, которое будет использовано
в директиве NAME и индентификаторах замещения.
Заметим, что в огромной модели памяти нет сегмента _BSS, и
определение групп полностью игнорируется. Вообще _BSS необязате-
лен, его определяют только при необходимости использования.
Лучший способ создать шаблон на языке ассемблера - скомпили-
ровать пустую программу в .ASM (используя опцию ТСС -S) и прос-
мотреть созданную ассемблерную программу.
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
Модель Идентификаторы замещения Указатели программ и данных
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
Крохотная, =_TEXT Code: DW _TEXT:xxx
Малая =_DATA Data: DW DGROUP:xxx
=_DGROUP
Компактная =_TEXT Code: DW _TEXT:xxx
=_DATA Data: DD DGROUP:xxx
=DGROUP
Средняя =filname_TEXT Code:DDxxx
=_DATA Data: DW DGROUP:xxx
=DGROUP
Большая =filname_TEXT Code: DDxxx
=_DATA Data: DD DGROUP:xxx
=DGROUP
Огромная =filname_TEXT Code: DDxxx
=filname_DATA Data: DDxxx
=filname_DATA
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
- 383,384 -
Таблица 12.5. Идентификаторы замещения и модели памяти
Определение констант данных и переменных
-----------------------------------------------------------------
Выбор модели памяти влияет также на способ определения конс-
тант данных, являющихся указателями к программе, данным или к то-
му и другому сразу. Табл.12.5 показывает, как будут выглядеть,эти
указатели. Здесь ххх - адрес, являющийся указателем.
Обратите внимание на то, что одни указатели используют ко-
|