|
Ассемблерные прграммы
Ассемблерные подпрограммы
- это процедуры и функции, объявленные с директивой
Assembler. В таких подпрограммах исполняемая часть не
содержит begin... end и состоит из единственного ассемблерного
оператора asm... end. Например:
Function LongMul(X,Y:Integer):LongInt;
Assembler;
asm
mov ax, X
imul Y {DX/AX содержат "длинный" результат}
end;
При компиляции ассемблерных подпрограмм
выполняется ряд оптимизаций кода, в том числе:
- параметры-значения строкового типа,
а также длиной в 1, 2 и 4 байта не копируются во временную
память, т.е. внутри подпрограммы они считаются параметрами-переменными
;
- компилятор не создает переменную
@Result для результата функции, и ссылка на эту переменную
в ассемблерной функции недопустима; исключением являются
функции, возвращающие значения строкового типа, для
них разрешается использовать ссылку на @Result;
- генерируются следующие команды на
входе в подпрограмму и на ее выходе:
push bp {Сохраняется ВР}
mov bp,sp {ВР содержит текущую границу
стека}
sub sp,Locals {Резервируется часть стека
для размещения локальных переменных}
.......
mov sp,bp {Восстанавливается граница
стека}
pop bp {Восстанавливается ВР}
ret Params {Из стека удаляются параметры
подпрограммы и осуществляется выход из
нее}
Здесь Locals - общая длина в байтах
всех объявленных в подпрограмме локальных переменных,
a Params - длина (в байтах) всех формальных параметров.
Если Locals и Params равны нулю, входной код не создается,
а выходной содержит единственную инструкцию RET.
Все локальные переменные Турбо Паскаль
размещает в стеке. Это относится как к обычным, так
и к ассемблерным подпрограммам. Для ссылки на локальные
переменные используется адресация по базе, задаваемой
парой DS: ВР, поэтому при входе в процедуру всегда создается
так называемый локальный стек: в регистр ВР помещается
текущая граница стека, а сама эта граница смещается
вверх на суммарную длину всех локальных переменных,
чтобы работа со стеком внутри подпрограммы не разрушила
локальные переменные. Например:
Procedure ...;
Assembler;
var
X: Word;
Y: Byte;
asm
mov X, ax {Компилируется в mov [BP-2],
ax}
mov ah,Y {Компилируется в mov ah,[BP-3]}
end;
Ассемблерные функции должны следующим
образом возвращать результат своей работы:
- длиной 1 байт (Byte, Char и
т.п.) - в регистре AL;
- длиной 2 байта (Integer, Word)
- в регистре АХ;
- длиной 4 байта (Pointer, LongInt)
- в регистрах DX (старшее слово) и АХ (младшее слово);
- типа Real - в регистрах DX,
BX, АХ (старшее слово - в DX, младшее в АХ);
- вещественных типов Single,
Double, Extended, Comp - в регистре ST (0) сопроцессора;
- строкового типа - во временной
области памяти, на которую ссылается @Result.
|