Что 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