Функции и процедуры на ассемблере

Главная / Ассемблер / Ассемблер и языки высокого уровня /

Лучшие книги по Ассемблеру Лучшие книги по Ассемблеру

Сделал подборку не новых, но проверенных книг по программированию на языке ассемблера. Если вы также как и я любите погружаться на низкий уровень, в те закоулки мира программирования, куда не всем путь открыт, то посмотрите. Возможно, что-то вам понравится. Подробнее...

В общих чертах о том, как использовать вставки на ассемблере в 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:

Модификатор alias в ассемблерной процедуре

Кроме того, есть ещё модификатор public. Его надо использовать, чтобы сделать функцию доступной вне текущего модуля:

procedure AsmUnit; assembler; [public, alias: 'ASM_UNIT'];
asm
  MOV  AX,  10
  MOV  BX,  5
  MUL  BX
end;

Честно говоря, не знаю, на что это влияет. В моих экспериментах получалось использовать ассемблерные процедуры из других модулей без модификатора public. Возможно, документация устарела и теперь это необязательно.

На этом пока всё. Об особенностях использования языка ассемблера ИНТЕЛ в Lazarus и FreePascal расскажу в другой раз.



Первые шаги в программирование Первые шаги в программирование

Главный вопрос начинающего программиста – с чего начать? Вроде бы есть желание, но иногда «не знаешь, как начать думать, чтобы до такого додуматься». У человека, который никогда не имел дело с информационными технологиями, даже простые вопросы могут вызвать большие трудности и отнять много времени на решение. Подробнее...

Инфо-МАСТЕР ®
Все права защищены ©
e-mail: mail@info-master.su