|
Как стать программистом Как устроен компьютер. Что такое программа. Как написать свою программу. И многое другое узнаете вы из этой книги. Получить бесплатно! |
Функции и процедуры на ассемблере
Главная / Ассемблер / Ассемблер и языки высокого уровня /В общих чертах о том, как использовать вставки на ассемблере в Delphi, Lazarus и FreePascal я рассказывал здесь. Сегодня расскажу ещё об одном способе - об ассемблерных процедурах и функциях.
Для того, чтобы создать чисто ассемблерную подпрограмму, которую затем можно использовать и в
ассемблерных вставках, в заголовок функции или процедуры надо добавить модификатор assembler. Например:
{$ASMMODE INTEL}
var z : WORD;
// Ассемблерная процедура
procedure AsmProc(x, y : WORD); assembler;
asm
MOV AX, x
ADD AX, y
MOV z, AX
end;
Поскольку в примерах используется синтаксис ИНТЕЛ, не забудьте установить соответствующий режим
(первая строка в примере). Здесь мы используем глобальную переменную z для передачи результата из процедуры в программу. Но в ассемблерной процедуре могут быть и локальные переменные:
procedure AsmVars; assembler; var a, b : WORD; asm MOV a, 1 MOV b, 2 MOV AX, a ADD AX, b MOV z, AX end;
Компилятор резервирует место в стеке для локальных переменных, при этом он вставляет некоторые команды в программу.
Ассемблерная функция может возвращать результат. В случае с синтаксисом ИНТЕЛ для этого используется макрос
@Result:
// Ассемблерная функция function SumXY(x, y : WORD) : WORD; assembler; asm MOV AX, x ADD AX, y MOV @Result, AX //Только для процессоров ИНТЕЛ end;
Пример использования описанных выше подпрограмм в программе:
WriteLn('X = ', 100, ', Y = ', 200);
AsmProc(100, 200);
WriteLn('X + Y = ', z);
WriteLn('X + Y = ', SumXY(100, 200));
asm
CALL AsmVars //Вызов ассемблерной процедуры в блоке asm
end;
WriteLn('1 + 2 = ', z);
Следующее мало кому пригодится, но, поскольку в документации об этом сказано, то и я расскажу.
Имя ассемблерной функции будет изменено компилятором. То есть метка для этой функции будет иметь
не такое имя, как указано в определении функции. Чтобы определить имя функции, которое можно
потом найти в ассемблерном коде (в файле с расширение .о), надо использовать модификатор alias:
// Использование алиаса (псевдонима) procedure AsmNOP; assembler; [alias:'ASM_NOP']; asm NOP end;
Допустим, имя исходного файла у нас asmtest.lpr. Тогда компилятор FreePascal создаст файл
asmtest.o. И в этом файле вы нигде не найдёте имя функции AsmNOP.
То есть вы не найдёте метки, с которой начинается код этой функции. Но если вы зададите алиас
(в нашем примере ASM_NOP), то этот алиас вы уже сможете найти в файле asmtest.o:
Кроме того, есть ещё модификатор public. Его надо использовать, чтобы сделать функцию доступной вне текущего модуля:
procedure AsmUnit; assembler; [public, alias: 'ASM_UNIT']; asm MOV AX, 10 MOV BX, 5 MUL BX end;
Честно говоря, не знаю, на что это влияет. В моих экспериментах получалось использовать ассемблерные
процедуры из других модулей без модификатора public. Возможно, документация устарела и теперь это необязательно.
На этом пока всё. Об особенностях использования языка ассемблера ИНТЕЛ в Lazarus и FreePascal расскажу в другой раз.
|
Вступить в группу "Основы программирования"
Подписаться на канал в РУТУБ Подписаться на рассылки по программированию |