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

=== Что 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
Category:Справочники