Многомодульные программы. Способ передачи параметров функциями языка Си, страница 2

·  По дальней ссылке, когда в стек помещается полная адресная пара аргумента. Предполагается, что основная программа и вызываемая программа работают с различными сегментами данных. Сегментная составляющая адреса помещается в стек вперед смещения. Это позволяет подпрограмме использовать операции LDS и LES для загрузки адресов из стека.

Встроенный код

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

Внутри вставки в программе Паскаля и Си могут:

·  Использоваться любые инструкции из набора кодов процессора 8086;

·  Использоваться метки и переменные, описанные вне блока ассемблерной вставки;

·  Использоваться константы, записанные в стиле ассемблера или языка высокого уровня;

·  Использоваться указатели в виде тип ptr [ИР].

Ограничения на содержимое ассемблерной вставки:

·  Нельзя использовать директивы определения переменных кроме  DB,  DW и DD;

·  Нельзя использовать большинство ассемблерных операторов таких, как OFFSET или SHR;

·  Не могут быть использованы операторы Struc, Record, Width и Mask;

·  Не могут использоваться макро директивы (например, IRP и IRPC) и макро операторы (например, <> или %);

·  Сегменты не доступны по именам, но доступны через соответствующие сегментные регистры.

·  Не должны изменяться значения регистров bp, sp, ss и ds.

·  Встроенный в Паскаль ассемблер всегда интерпретирует параметр VAR как 32-битный указатель ES:[регистр]. Поэтому сначала нужно параметр VAR через команду les загрузить в регистр, а затем использовать: les регистр,VAR-параметр  mov LS:[регстр],значение.

Обычно внутри вставки можно использовать регистры ax,bx,cx,dx, т.к. большинство компиляторов не накладывают требования сохранности содержимого этих регистров между соседними предложениями программы. Однако к использованию регистров нужно подходить осторожно, т.к., например в языке С, использование регистров si и  di может привести к невозможности оптимизации основного кода программы компилятором, т.к. он использует эти регистры для размещения регистровых переменных.

В отличие от Паскаля, в языке Си внутри ассемблерных вставок могут быть использованы директивы описания переменных. При этом вставки могут быть размещены как внутри описания функций, так и вне их. В первом случае производятся, как правило, вставки исполняемых операторов, а во втором – описаний данных.

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

Паскаль-Ассемблер

Для включения в состав программы на Паскале модулей, написанных на ассемблере, следует, прежде всего, обратить внимание на соотношение основных типов этих двух языков. Основные типы аргументов, передаваемых по значению и по ссылке, а также типы значений, возвращаемых функциями и способы возврата вычисленных значений приводятся в следующих двух таблицах:

Таблица 1 Представление типов Паскаля для аргументов, передаваемых через стек, через типы ассемблера.

По значению

По ссылке

Через стек сопроцессора

Char

Byte

VAR всех типов

Dword

Single

Byte

Byte

pointer

Dword

Double

Boolean

Byte

longint

Dword

Extended

0..255

Byte

string

Dword

Comp

0..65535

Word

множества

Dword

Word

Word

массивы >4 байт

Dword

Integer

Word

записи > 4 байт

Dword

Real

3 words

Array

как есть,

Record

до 4 байт

Таблица 2 Типы и размеры значений, возвращаемых функциями Паскаля