Sources
Delphi Russian Knowledge Base
DRKB - база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Программирование ассемблером в Delphi

20.04.2004
Александр Баранецкий

Каждый день множество программистов (кроме опытных) в Delphi, используя код высокого уровня, пишут свои программы. Как правило, пренебрегая таким понятием как Assembler, имеется ввиду в строенный в DELPHI. Конечно, тяжело сказать, что на голом «асе» можно сотворить великолепный шедевр имеется ввиду красота - VCL (Visual Component Library). Особенно относительно начинающих программистов, которые только начинают учить IDE. Но зато можно повысить скорость какого нибудь математического или системного алгоритма.

Сегодня я представляю на ваш суд статью по «асму». Скорее всего, она будет интересна начинающим программерам. Я не мастер, но всё же...

Программирование АССЕМБЛЕРОМ в "Delphi"

Для начала несколько основных команд.

MOV - предназначена для занесения в ячейку памяти значения. Например:

var
  x: integer;
begin
  Mov X, 10 // Занесение в Х значение 10 // X:=10;
  Mov eax, 45 //Занесение в быстрый регистр
  Mov ebx, eax //Присвоения значения одного регистра другому
  Mov x.edx //Занесение в х значения edx

Первый параметр присваивающий объект, второй присеваемое значение.

ADD - Предназначена для прибавления к объекту значения. Значения передаются через запитаю. Например :

add eax,2
add x,76 

Первый параметр принимающий объект, второй добавляемое значение.

SUB - Предназначена для вычитания от объекта значения. Значения передаются через запитаю. Например :

sub eax,18
Sub x,6 

Первый параметр объект от которого отнимается, второй отнимаемое значение.

IMUL - команда умножения

IDIV - команда деления

CMP - Команда проверки

JNZ,JMP,JA - команды перехода.

Теперь перейдем к практическим примерам:

// 1 Функция сложения.

function plus(x, y: integer): integer;
asm
  mov eax,x
  add eax,y
end;

{
Функция вернет сумму «x» и «y». Сперва заносим «х» (move eax,x) потом
прибавляем к уже имеющемуся «y» (add eax,y).
}
// 2. Функция умножения

function Umnojenie(x, z: integer): integer;
asm
  mov ebx,z
  mov eax,x
  imul ebx
end;

{
Заносим в обратном порядке «x» и «z» Отдаем команду на
умножение первого значения на второе «imul ebx ».
}

// 3. Функция вычитания

function Minus(x, y: integer): integer;
asm
  sub x,y
end;

// Просто отнимаем одно от другого

// 4 Функция деления

function divider(x, y: integer): integer;
asm
  mov ebx,y {1}
  cdq {2}
  idiv ebx {3}
end;

Эта функция отличается от остальных методом применения операторов:

  1. Занесение значения.
  2. Предварительная обработка.
  3. Деление.

Это были простейшие математические операторы, теперь мы рассмотрим более сложные операторы цикла и условие

Цикл на «асме» заключается в том что создается контрольный объект и при достижении определенного условия не происходи перехода к начальной контрольной точке отчета цикла.

procedure asm_cycle;
label
  lb;
var
  d: integer;
begin
  asm
    mov ebx,0
    mov d,0
    lb:
    add d,1
    inc ebx
    cmp ebx,10
    jnz lb
    mov ebx,0
  end;
  Writeln(d);
end;

Метка lb нужна, чтобы назначить контрольную точку начала операторов цикла. Переменная «d:integer» для проверки результатов работы цикла. С зарезервированного слова ASM начинаем анализ. Mov edx,0 «edx» выступает как контрольный регистр в нем фиксируется количество повторений. А с самого начало он указывает с какой величины пойдет отсчет. Например

mov edx,0 = for i := 0 to .. do,
mov edx,43 = for i:=43 to ..do

Мы установим его в 0 чтобы отсчет шел с нуля. Переменную d мы тоже обнулим. Третья строка это метка начала после нее идут операторы цикла. Следующий оператор наш рабочий оператор. У нас он 1 но может быть множество. Inc edx добавляем в регистр 1 шаг пройденного цикла если пропустить то цикл будет идти вечно. cmp ebx,10 Один из основных операторов он проверяет не достиг ли цикл верхний предел. Проверка идет в самом конце. Если вернет FALSE то срабатывает следующий оператор перехода на метку т.е в начало цикла и все повторяется до тех пор пока cmp не вернет TRUE в следствии чего не сработает оператор перехода JNZ. Последними операторами обнуляем счетчик и показываем результат.

Условный оператор IF..THEN..ELSE.

procedure if_sample(x: integer);
var
  res: integer;
label
  exit, lb;
begin
  asm
    cmp x,0
    jnz lb
    mov res,45
    jmp exit
    lb:mov res,0
    exit: mov eax,0
  end;
  Writeln(res);
end;

На PASCAL этот оператор пишется так

if x = 0 then
  x:=45
else
  x:=0;

Сначала идет проверка не равен ли х нулю, если не равен то переход на метку ld, на которой оператор обнуления. А если равен, то оператор перехода на ld не срабатывает. Срабатывает mov res,45. После которого состоится переход на метку EXIT. В «асме» желательно прописывать свою метку (у нас EXIT), которая по необходимости выйдет из процедуры.

И последнее. Вызов внешней процедуры. Допустим, надо вызвать внешнюю процедуру.

procedure call_s(x, d: integer; bol: boolean);

Для вызова внешних модулей применяется метод CALL.

procedure call_sample;
asm
  mov eax,4
  mov edx,34
  mov cl,0
  call call_s
end;

Сперва передаются параметры последовательно а потом сам вызов.

На этом мой маленький туториал окончен. Все примеры вы найдете в приложенном файле pr_asm. Это маленькое консольное приложение, в котором представлены все примеры с комментариями.

P.S. Я не мастер в «асме», и эта статья не сделает вас гениями, она лишь призвана показать некоторые стандартные методы «паса», интерпретированные в «асм». Мастера «асма», не смейтесь надо мной сильно, так как я уже сказал, что я не мастер, я просто энтузиаст в «асме».

В следующей статье я продолжу описание более продвинутых операторов и методов а также попробуем написать маленькое «асм» приложение.

Previous page:
Изучаем ассемблер в Delphi
Top:
DRKB
Next page:
Как присвоить значение полям записи с помощью ассемблера?