Иллюстрированный самоучитель по Turbo Pascal

Внешние процедуры (функции)

С помощью внешних процедур (функций) можно осуществить вызов из программы процедур или функций, написанных на языке ассемблера. Ассемблер обеспечивает компиляцию программ, написанных на машинно-ориентированном языке программирования низкого уровня. В Турбо Паскале есть собственный встроенный ассемблер см. гл.12). В этом разделе речь идет о программах, написанных и откомпилированных с помощью внешнего ассемблера, такого как, например, ассемблер фирмы MicroSoft или Turbo Assembler фирмы Borland.

Машинно-ориентированный язык ассемблера предоставляет квалифицированному программисту богатейшие возможности использования всех особенностей архитектуры ПК. Ассемблерные программы выполняются значительно быстрее и занимают меньший объем памяти, чем программы, написанные на Турбо Паскале, однако низкий уровень языка ассемблера существенно снижает производительность труда программиста и резко усложняет отладку программ. Как правило, на языке ассемблера пишутся сравнительно небольшие фрагменты программ, в которых используются недоступные из Турбо Паскаля особенности архитектуры ПК.

Внешняя процедура (функция) в программе, написанной на Турбо Паскале, объявляется своим заголовком, за которым следует стандартная директива EXTERNAL, например:

Function LoCase (ch: char):char; external;
Procedure Swapping (var a,b; N:word); external;

Как видно из этих примеров, тело внешней процедуры (функции) отсутствует – его заменяет директива EXTERNAL. Для подключения ассемблерной программы необходимо предварительно ее откомпилировать и получить объектный файл с расширением OBJ, содержащий перемещаемый код ассемблерной программы. Непосредственно перед описанием внешней процедуры (функции) в тело основной программы вставляется директива компилятора {$L<имя файла>}, где <имя файла> – имя OBJ-файла. Диск и каталог, в котором следует искать этот файл, если он не обнаружен в текущем каталоге, указываются опцией OPTIONS/DIRECTORIES/OBJECT DIRECTORIES (см.прил.1).

Перед передачей управления внешней процедуре (функции) программа помещает параметры обращения в программный стек в том порядке, как они перечислены в заголовке процедуры (функции). Ассемблерная процедура должна сохранить регистры ВР, SP, SS и DS центрального процессора в самом начале своей работы и восстановить содержимое этих регистров перед возвратом управления в программу. Остальные регистры можно не сохранять и соответственно не восстанавливать.

Параметры могут передаваться по ссылке или по значению. Если параметр передается по ссылке, в стек помещается указатель, содержащий абсолютный адрес параметра, если по значению – в стек помещается сам параметр, точнее – его значение. Все параметры-переменные, т.е. параметры, объявленные в заголовке с предшествующим словом VAR, всегда передаются по ссылке. Параметры-значения могут передаваться по ссылке или по значению в зависимости от длины внутреннего представления соответствующего параметра.

В общем случае используется следующее правило: если длина внутреннего представления параметра-значения составляет 1, 2 или 4 байта, он передается своим значением, т.е. его значение помещается в стек. Точно так же через стек передаются и все вещественные данные длиной в 4, 6, 8 и 10 байт (в версии 4.0 эти данные передаются через стек сопроцессора 8087/80287, начиная с версии 5.0 – через стек центрального процессора 8086/80486). Во всех остальных случаях, если длина внутреннего представления больше 4 байт, соответствующий параметр передается по ссылке.

Ассемблерные функции в зависимости от длины внутреннего представления результата должны возвращать его через регистры центрального процессора или сопроцессора по следующим правилам:

  • длиной в 1 байт – в регистре AL;
  • длиной в 2 байта – в регистре АХ;
  • длиной в 4 байта – в регистрах DX:AX (старшее слово в DX);
  • тип REAL (6 байт) – в регистрах DX:BX:AX;
  • типы SINGLE, DOUBLE, EXTENDED и СОМР – через стек сопроцессора 8087/80486;
  • указатели – в регистрах DX:AX (сегмент в DX);
  • строки возвращаются по ссылке: адрес начала строки помещается в DX:AX (сегмент в DX).

Все ассемблерные процедуры должны размещаться в сегменте с именем CODE или CSEG, или с именем, оканчивающимся на _ТЕХТ; инициализированные локальные Переменные помещаются в сегмент с именем CONST или с именем, оканчивающимся на _DATA. Все другие локальные переменные необходимо размещать в сегменте с именем DATA или DSEG, или с именем, оканчивающимся на _BSS. Любые другие объявления сегментов игнорируются.

Все имена, объявленные в интерфейсной части модулей программы, написанной на Турбо Паскале, становятся доступны ассемблерной процедуре (функции) после их объявления директивой EXTRN. Точно так же все имена ассемблерных процедур и функций, которые должны быть доступны программе на Турбо Паскале, следует объявлять директивой PUBLIC.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.