Что Delphi знает об ассемблере

Материал из DRKB

Что Delphi знает об ассемблере[править | править код]

Сегодня мы рассмотрим вопрос применения ассемблера в программах, написанных на Delphi.

Итак, что же Delphi "знает" об ассемблере?


Команды процессора[править | править код]

Ура, начиная с шестой версии, в популярном продукте Borland реализована поддержка всех команд процессора, включая команды расширений MMX, SSE, 3DNow! Теперь нет необходимости вместо простой команды rdtsc писать dw 310Fh .


Доступ к переменным[править | править код]

Delphi позволяет легко обращаться по имени к глобальным или локальным переменным:

var
  i: integer;
begin
  i := 0;
  asm
    mov eax,i
    inc eax
    mov i,eax
  end;
end;


Доступ к параметрам[править | править код]

К переменным, передаваемым процедуре в качастве параметров доступ осуществляется также легко:

procedure SomeProc(i: integer);
begin
  asm
    mov eax,i
    inc eax
    mov i,eax
  end;
and;


Передача параметров по ссылке[править | править код]

Если параметр процедуры или функции объявляется как var, то вместо значения переменной передается указатель на эту переменную. Поэтому внутри ассемблерного блока этот параметр будет представлять собой 32-разрядный указатель вместо собственно переменной. Поэтому обращаться к параметру, переданному как var надо следующим образом:

procedure SomeProc(var i: integer);
begin
  asm
    mov eax,i
    inc dword ptr [eax]
  end;
end;


Регистровое соглашение о вызове[править | править код]

В языке Object Pascal, использующемся в Delphi, по умолчанию действует регистровое соглашение о вызове. Согласно этому соглашению, первые три 32-разрядных параметра передаются в регистры eax,edx и ecx. Следовательно, если функция объявлена следующим образом

function SomeFunc(i1, i2, i3 : integer): integer;

то можно рассчитывать, что переменная i1 содержится в регистре eax, i2 - в edx, i3 - в ecx.

Если объявлен некий метод

procedure TSomeObject.SomeProc(i1, i2 : integer);

то i1 передается в edx, i2 - в ecx, а в eax передается неявно заданный параметр Self!


Доступ к полям записи[править | править код]

Обращение к полям записи также достаточно просто:

type
  TSomeRec = record
    i: integer;
    c: char;
  end;
procedure SomeProc(var SomeRec: TSomeRec);
begin
  asm
    mov [eax].TSomeRec.i, 33
    mov [eax].TSomeRec.c,'a'
  end;
end;


Локальные метки[править | править код]

Хотя использование меток и считается дурным тоном в программировании на языках высокого уровня, в ассеблерных программах без них не обойтись. Внутри блока asm..end можно, без предварительного объявления, использовать метки, начинающиеся с символа '@'.


Сохранение регистров[править | править код]

В ассемблерных процедурах и функциях нужно сохранять регистры EDI, ESI, ESP, EBP, and EBX и свободно оперировать регистрами EAX, ECX, and EDX.


Вызов динамических и виртуальных методов[править | править код]

Существуют две директивы для доступа к динамическим и виртуальным методам из ассемблерных вставок.

VMTOFFSET - возвращает смещение (в байтах) указателя виртуального метода относительно начала таблицы виртуальных методов (VMT).

DMTINDEX - возвращает индекс динамического метода в таблице динамических методов.

Примеры вызовов виртуального и динамического методов:

procedure CallDynamicMethod(e: TExample);
asm
  push esi
  mov  eax,e
  mov  esi, DMTINDEX TExample.DynamicMethod
  call System.@CallDynaInst
  pop  esi
end;

procedure CallVirtualMethod(e: TExample);
asm
  mov     eax, e
  mov     edx, [eax]
  call    dword ptr [edx + VMTOFFSET TExample.VirtualMethod]
end;



Source: http://delphiworld.narod.ru
ID: 00689