Использование turbo pascal с языком ассемблера. Встроенный ассемблер, страница 14

Inline(<$1234/>$44);

генерирует 3 байта кода: $34,$44,$00.

Значение идентификатора    переменной    в   элементе   Inline

представляет собой смещение адреса переменной  внутри  ее  базового сегмента.   Базовой  сегмент  глобальной  переменной  -  переменной объявленной  на  внешнем  уровне  в  программе   или   модуле   или типированной константы - это сегмент данных,  к которому обращаются через  регистр  DS.  Базовый   сегмент   локальной   переменной   переменной,  объявленной  внутри текущей подпрограммы - это сегмент стека.  В этом случае переменная смещена относительно регистра  BP, который автоматически ссылается на сегмент стека.

Примечание: Регистры  BP,  SP,  SS  и DS должны быть сохранены оператором Inlile; все остальные регистры могут изменяться.

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

Процедура FillWord запоминает Count слов в значении Data  в памяти, начиная с первого байта Dest.

procedure FillWord(var Dest; Count, Data: Word);

begin

Inline(

$C4/$BE/Dest/       {LES DI, Dest[BP]}

$8B/$8E/Count/      {MOV CX, Count[BP]}

$8B/$86/Data/       {MOV AX, Data[BP]}

$FC/                {CLD}

$F3/$AB);           {REP STOSW}

end;

Оператор Inline   может   быть   свободно   смешан  с  другими операторами в операторной части блока.

Директива Inline.

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

-----------------¬

директива Inline ---Ў¦оператор  inline¦

L----------------Когда вызывается обычная процедура или функция (включая  и те, которые  содержат  операторы  Inline),  компилятор  генерирует код, который  помещает  параметры  (если  они  есть)  в  стек  и   затем генерирует  инструкцию  CALL  для  вызова  процедуры  или  функции.

Однако, когда вы вызываете Inline процедуру или функцию, компилятор вместо  генерации  CALL  вставляет  код  из  этой директивы Inline.

Короткий пример двух процедур Inline:

procedure DisableInterrupts; Inline($FA);      {CLI}

procedure EnableInterrupts; Inline($FB);       {STI}

Когда вызывается  DisableInterrupts - генерируется 1 байт кода

- инструкция CLI.

Процедуры и  функции,  объявленные с директивой Inline,  могут иметь параметры;  однако,  к параметрам нельзя обращаться по  имени

(но  к  другим  переменным  можно).  Также  из-за  того,  что такие процедуры и  функции  в   действительности   макро,   в   них   нет автоматического  входного  и  выходного  кода,  и  не  должно  быть инструкции возврата.

Следующая функция   умножает   два  целых  значения,  создавая результат типа LongInt:

function LongMul(X, Y: Integer): Longint;

Inline (

$5A/          {POP AX; POP X}

$5E/          {POP DX; POP Y}

$F7/$EA);     { IMUL DX; DX : AX = X * Y}

Заметьте отсутствие   входного  и  выходного  кода  и  пропуск инструкции выхода.  Здесь они не требуются,  так как  эти  4  байта вставляются в остальной код при вызове LongMul.

Директива Inline  применяется  только   для   очень   коротких процедур и функций ( < 10 байт).

Так как Inline процедуры и функции - это макро,  они не  могут использоваться как аргументы оператора @ и функций Addr, Ofs и Seg.

ПРИЛОЖЕНИЕ  В.

СПРАВОЧНЫЙ МАТЕРИАЛ.

Это приложение посвящено определенному  справочному материалу, включая   таблицу  кодов  ASCII,  коды  сканирования  клавиатуры  и расширенные коды.

Коды ASCII.

Американский стандартный  код для обмена информацией (ASCII) это код,  который переводит алфавитные и цифровые символы,  знаки и управляющие  команды  в  7-ми  битовый двоичный код.  В таблице В.1

показаны и печатаемые символы, и управляющие символы.