Совместное с Турбо Паскалем использование данных
Далее следует содержимое главы.
Директива компилятора $L и внешние подпрограммы
Два ключевых момента при использовании Турбо Ассемблера с Турбо Паскалем - это директива компилятора (Турбо Паскаля) {$L} и описание внешней (external) подпрограммы. Директива {$L MYFILE.OBJ} приводит к тому, что Турбо Паскаль будет искать файл объектный MYFILE.OBJ (файл в стандартном пригодном для компоновки формате MS-DOS) и компоновать его с вашей программой Турбо Паскаля. Если у файла в директиве {$L} расширение не указывается, то подразумевается расширение .OBJ.
Каждая процедура или функция Турбо Ассемблера, которую вы хотите сделать доступной в программе Турбо Паскаля, должна объявляться, как идентификатор PUBLIC, и ей должно соответствовать в программе описание external (внешняя). Синтаксис описания внешней процедуры или функции в Турбо Паскале аналогичен опережающему (forward) описанию:
procedure AsmProc(a : integer; b : real); external;
function AsmFunc(c : word; d : byte); external;
Эти описания должны соответствовать следующим описаниям в программе Турбо Ассемблера:
CODE SEGMENT BYTE PUBLIC AsmProc PROC NEAR PUBLIC AsmProc . . . AsmProc ENDP AsmFunc PROC FAR PUBLIC Bar . . . AsmFunc ENDP CODE ENDS
Описание внешней (external) процедуры Турбо Паскаля должно находиться на самом внешнем уровне программы или модуля, то есть оно не должно быть вложенным по отношению к другому описанию процедуры или функции. Попытка описать процедуру или функцию на любом другом уровне приведет к ошибке этапа компиляции.
Турбо Паскаль не делает проверку, чтобы убедиться, что все процедуры, описанные с атрибутами NEAR или FAR, соответствуют ближним или дальним подпрограммам в программе Турбо Паскаля. Фактически, он даже не проверяет, являются ли метки AsmProc и AsmFunc именами процедур. Поэтому вы должны обеспечить, чтобы описания в Ассемблере и Паскале были правильными.
Директива PUBLIC
В Турбо Паскале доступны только те метки Ассемблера, которые объявлены в модуле на языке Ассемблера, как общедоступные (PUBLIC). Метки представляют собой единственные объекты, которые могут передаваться из языка Ассемблера в Турбо Паскаль. Более того, каждой общедоступной метке должно соответствовать описание процедуры или функции в программе Турбо Паскаля, иначе компилятор выдаст сообщение об ошибке. Причем не требуется, чтобы общедоступная метка была частью описания PROC. Что касается Турбо Паскаля, то для него описания:
AsmLabel PROC FAR PUBLIC Bar
и
AsmLabel: PUBLIC Bar
эквивалентны.
Вы можете определять такие идентификаторы как PUBLIC только в сегменте CODE. Турбо Паскаль не разрешает определения идентификаторов PUBLIC в сегменте данных, поэтому создаваемые вами ассемблерные модули для компоновки с программой на Турбо Паскале также не должны иметь в сегменте данных.
Директива EXTRN
Модуль Турбо Ассемблера может обращаться к любой процедуре, функции, переменной или типизованной константе Турбо Паскаля, которая описывается на самом внешнем уровне программы или модуля, с которым она компонуется. (Заметим, что это включает в себя переменные, описанные после директивы компилятора {$L} и внешние описания, связанные с данным модулем.) Метки и обычные константы Турбо Паскаля языку Ассемблера недоступны.
Примечание: Эти включает в себя переменные, указанные после директивы компилятора $L и описаниях external, связанных с данным модулем.
Предположим, в вашем программе Турбо Паскаля описываются следующие глобальные переменные:
var a : byte; b : word; c : shortint; d : integer; e : real; f : single; g : double; h : extended; i : comp; j : pointer;
В программе на языке Ассемблера вы можете получить доступ ко всем этим переменным с помощью описаний EXTRN:
EXTRN A : BYTE | 1 байт
| EXTRN B : WORD | 2 байта
| EXTRN C : BYTE | в Ассемблере значения со знаком и без знака интерпретируются одинаково | EXTRN D : WORD | то же самое | EXTRN E : FWORD | 6-байтовое действительное значение (обрабатывается программно)
| EXTRN F : DWORD | 4-байтовое значение с плавающей точкой в формате IEEE | EXTRN G : QWORD | 8-байтовое значение с плавающей точкой (двойной точности) в формате IEEE
| EXTRN H : TBYTE | 10-байтовое значение с плавающей точкой во временном формате | EXTRN I : QWORD | 8-байтовое целое со знаком в формате IEEE (сопроцессор 8087)
| EXTRN J : DWORD | указатель Турбо Паскаля |
Аналогичным образом можно получить доступ к процедурам и функциям Турбо Паскаля, включая библиотечные. Предположим, у вас имеется модуль Турбо Паскаля, который выглядит следующим образом:
unit Sample; { Пример модуля, в котором определяется нескольку процедур Паскаля, вызываемых из процедуры на языке Ассемблера }
interface
procedure TestSample;
procedure PublicProc; { для обращения извне должна быть дальнего типа } inplementation
var A : word;
procedure AsmProc; external; {$L ASMPROC.OBJ}
procedure PublicProc; begin { PublicProc } Writeln("В PublicProc"); end { PublicProc }
procedure NearProc; { должна быть ближнего типа } begin { NearProc } Writeln("B NearProc"); end; { NearProc }
{$F+} procedure FarProc { должна иметь дальний тип согласно директиве компилятора } begin { FarProc } Writeln("B FarProc"); end { FarProc }
{$F-}
procedure TestSample; begin { TestSample } Writeln("B TestSample"); A := 10; Writeln("Значение A перед ASMPROC = ",A); AsmProc; Writeln("Значение A после ASMPROC = ",A); end { TestSample };
end.
Процедура AsmProc вызывает процедуры PublicProc, NearProc или FarProc, используя директиву EXTRN следующим образом:
DATA SEGMENT WORD PUBLIC ASSUME DS:DATA EXTRN A:WORD ; переменная из модуля DATA ENDS
CODE SEGMENT BYTE PUBLIC ASSUME CS:CODE EXTRN PublicProc : FAR ; дальняя процедура (экспортируется модулем) EXTRN NearProc : NEAR ; ближняя процедура (локальная для модуля) EXTRN FarProc : FAR ; дальняя процедура (локальна, но задана, как дальняя) AsmProc PROC NEAR PUBLIC AsmProc CALL FAR PTR PublicProc CALL NearProc CALL FAR PTR FarProc mov cx,ds:A ; взять переменную из модуля sub cx,2 ; изменить ее mov ds:A,cx ; записать ее обратно RET AsmProc ENDP CODE ENDS END
Основная программа, которая проверяет эту программу на Ассемблере и модуль Паскаля, выглядит следующим образом:
program TSample; uses Sample; begin TestSample; end.
Чтобы сформировать пример программы с помощью компилятора, работающего в режиме командной строки, и Ассемблера, используйте следующие команды (или командный файл):
TASM ASMPROC TPC /B SAMPLE TSAMPLE
Так как внешняя подпрограмма должна объявляться в программе Турбо Паскаля на самом внешнем уровне процедур, вы не можете для доступа к объектам, являющимся локальными по отношению к процедурам или функциям использовать описания EXTRN. Однако, ваша программа на Турбо Ассемблере при вызове из программы Турбо Паскаля может получить эти объекты, как значения параметров-переменных.
1 2 3 4 5 6 7 8
8 8 8
|