- Компилятор не распределяет переменную результата функции и ссылка на символ @Result является ошибкой. Строковые функции являются исключением из этого правила. Они всегда используют указатель @Result, который распределяется вызывающей программой.
- Компилятор не генерирует кадра стека для процедур и функций без параметров и локальных переменных.
- Автоматически генерируется код входа и выхода для ассемблерных процедур и функций, выглядящих как:
push bp
mov bp,sp
sub sp,Locals
...
mov sp,bp
pop bp
ret Params
где Locals - размер локальных переменных, Params - размер параметров. Если Locals и Params ноль, то входного кода нет, а код выхода состоит из инструкции RET.
Функции, использующие директиву Ассемблера, должны возвращать результаты:
- Функции порядкового типа (Integer, Char, Boolean и перечислимые типы возвращают результаты в AL (8-битное значение),
AX (16-битное значение), или DX:AX (32-битное значение).
- Функции типа Real возвращают результат в DX:BX:AX
- Функции с результатами типа 8087 (Single, Double, Extended и
Comp) возвращают его в регистре ST(0) сопроцессора 8087.
- Результат типа указатель возвращается в DX:AX.
- Результат типа строка возвращается через временную память, на которую указывает @Result.
Ассемблерная директива во многом сравнима с директивой
external, а ассемблерные процедуры и функции должны следовать тем же правилам, что и external процедуры и функции. Следующие примеры демонстрируют некоторые отличия между операторами asm в обычных и ассемблерных фунциях. Первый пример использует оператор asm в обычной функции для преобразования строки в прописные буквы.
Заметим, что значение параметра Str в этом случае ссылается на локальную переменную, поскольку компилятор автоматически генерирует входной код, который копирует действительный параметр в локальную память.
function UpperCase(Str: String): String;
begin
asm
cld
lea si,Str
les di,@Result
SEGSS lodsb
stosb
xor ah,ah
xchg ax,cx
jcxz @3
@1:
SEGSS lodsb
cmp al,'a'
ja @2
cmp a1,'z'
jb @2
sub a1,20H
@2:
stosb
loop
@3:
end;
end;
Второй пример - это ассемблерная версия функции UpperCase. В
этом случае Str не копируется в локальную память, и функция должна интерпретировать Str как var параметр.
function UpperCase(S: String): String; assembler;
asm
push ds
cld
lds si,Str
les di,@Result
lodsb
stosb
xor ah,ah
xchg ax,cx
jcxz @3
@1:
lodsb
cmp a1,'a'
ja @2
cmp a1,'z'
jb @2
sub a1,20H
@2:
stosb
loop @1
@3:
pop ds
end;
ГЛАВА 23.
РЕДАКТИРОВАНИЕ АССЕМБЛЕРНОГО КОДА.
Процедуры и функции, написанные на ассемблере могут быть связаны с программами и модулями Turbo Pascal с помощью директивы компилятора $L. Исходный файл на ассемблере должен быть ассемблирован в объектный файл (.OВJ) с помощью Turbo Assembler. С
программой или модулем можно связать несколько объектных файлов с помощью нескольких директив $L.
Процедуры и функции, написанные на ассемблере, должны быть объявлены в программе или модуле на Паскале, как external, например:
function LoCase(Ch: Char): Char; external;
В соответствующей исходной программе на ассемблере, все процедуры и функции должны быть расположены в сегменте с именем
CODE или CSEG, или в сегменте, чье имя оканчивается _TEXT и имена внешних процедур и функций должны быть в директиве PUBLIC.
Вы должны быть уверены, что процедура или функция на ассемблере соответствует ее определению на Паскале по модели вызова
(NEAR или FAR), числу параметров, типу параметров и типу результата.
Исходный файл на ассемблере может объявлять инициализированные переменные в сегменте с именем CONST или в сегменте, чье имя оканчивается _DATA и неинициализированные переменные в сегменте с именем DATA или DSEG, или в сегменте, чье имя оканчивается _BSS.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.