TURBO PASCAL |
Новости
|
Процедуры и функции ассемблераДо сих пор мы рассматривали конструкцию asm...end, как опе- ратор с обычной частью begin...end. Директива assembler в Borland Pascal позволяет вам писать на встроенном ассемблере целиком про- цедуры и функции без необходимости begin...end. Приведем пример функции на ассемблере: function LongMul(X, Y: Integer) : Longint; assembler; asm mov ax,X imul Y end; Директива assembler приводит к тому, что Borland Pascal вы- полняет при генерации кода следующую оптимизацию: - Компилятор не генерирует код для копирования парамет- ров-значений в локальные переменные. Это влияет на все па- раметры-значения строкового типа и другие значения-пара- метры, размер которых не равен 1, 2 или 4 байтам. Внутри процедуры или функции такие параметры должны интерпретиро- ваться, как если бы они были параметрами-переменными. - Компилятор не выделяет память для результата функции, и ссылка на идентификатор @Result будет ошибкой. Однако строковые функции являются исключением из этого правила - они всегда имеют указатель @Result, который распределяется пользователем. - Для процедур и функций, не имеющих параметров и локальных переменных, компилятор не генерирует кадров стека. - Для процедуры и функции на ассемблере автоматически гене- рируется код выхода: push bp ; присутствует, если Locals <> 0 или ; Params <> 0 mov bp,sp ; присутствует, если Locals <> 0 или ; Params <> 0 sub sp,Locals ; присутствует, если Locals <> 0 ... mov sp,bp ; присутствует, если Locals <> 0 pop bp ; присутствует, если Locals <> 0 или ; Params <> 0 ret Params ; всегда присутствует где Locals - размер локальных переменных, а Params - раз- мер параметров. Если и Locals и Params = 0, то кода входа не будет, и код выхода состоит просто из инструкции RET. Функции, использующие директиву assembler, должны возвращать результат следующим образом: - результаты функции порядкового типа (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. Директива assembler во многом похожа на директиву 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 al,'a' ja @2 cmp al,'z' jb @2 sub al,20H @2: stosb loop @1 @3: end; end; Второй пример на ассемблере представляет собой версию функ- ции UpperCase. В этом случае Str не копируется в локальную па- мять, и функция должна интерпретировать Str, как параметр-пере- менную. 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 al,'a' ja @2 cmp al,'z' jb @2 sub al,20H @2: stosb loop @1 @3: pop ds end; |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |