Скорее Вы форумом ошиблись ) procedure TForm1.Button1Click(Sender: TObject); var p:pchar; begin p:=pchar(Button1.Caption); asm pushad push MB_ICONINFORMATION push 0 push p push 0 call MessageBoxA popad end; end; Так подойдет?
drmist- нет... это вызов простой API функции... а хотелось юы что-то типа mov eax, Form1.Handle Эт конечно не правильный вариант но смысл раскрывает... Quantum - я тож так думал... но я там запутался немного, поэтому и решил тут спросить...
Quantum Решил послушаться Вашего совета и еще раз залесть в CPU... Delphi-код: Код (Text): mov eax, [ebp-$14] call TWinControl.GetHandle mov [ebp-$18], eax Мой код: Код (Text): mov eax, MainForm call TWinControl.GetHandle push eax Разница только в типе адресации к перемненным... ну еще у меня вместо пересылки результата в переменную, я ее в стек. Так вот, сама Дельфя ругается на call TWinControl.GetHandle в моем коде, т.к. функция все-таки приватная... говорит, что мол GetHandle ей не знаком... посоветуйте пожалуйста, как ЭТО обойти...
Ой кошмар! К чему так извращаться-то? Написать процедуру/фунцию, из которой вызвать TWinControl.GetHandle, и вызвать её из асмовской вставки.
Sl4v4 Это понятно, но как быть, если мне нужны скажем свойства 30-40 классов VCL и не только... т.е. можно конечно продублировать исходные классы, наделать public-клонов функций - но это как Вы сказали . Ладна, всем пасиба за помощь... пойду писать реал-тайм генератор смещений фнкций в классах... пожелайте мне удачи
Ginger > "пойду писать реал-тайм генератор смещений фнкций в классах... пожелайте мне удачи" Ну-ну, желаю удачи Думаю понятно, что свойство это фикция компилятора из разряда compiler magic. На самом деле в зависимости от объявления компилятор может заменять вызов св-ва на 1) непосредственное обращение к полю экземпляра объекта, 2) вызов статического метода, 3) вызов виртуального метода, 4) вызов динамического метода. Соответственно и асм-реализация для этих случаев будет разной. Поскольку поля и методы чтения\записи свойств обычно объявляются private или protected, то обратиться к ним по имени из другого модуля нельзя. Поэтому если очень хочется реализовать вызов св-в на асме, то нужно дизасмить примеры вызова св-в на паскале и брать реальный асм-листинг без всяких паскальских псевдо-имен. Например, настоящий вызов статического метода TWinControl.GetHandle будет выглядеть как относительный call XXXXXXXXh, где XXXXXXXXh - относительное смещение TWinControl.GetHandle от инструкции следующей за call. Чтение приватного поля будет выглядеть просто как mov reg32,[eax+XX], где в eax указатель на объект, а XX - смещение поля от начала записи объекта. Вызовы виртуальных и динамических методов идут через call [reg32+XX], где reg32 содержит указатель на VMT или DMT класса, а XX - смещение метода в таблице. Поскольку указатели VMT и DMT вытаскиваются из указателя на сам объект, то соответсвенно и нет проблем с реализацией на асме обращений к полям, виртуальным и динамических методам - подсмотрел как идет вызов в примере и скопировал. А вот со статическими методами могут быть проблемы - мало того, что нужно пересчитать относительное смещение в call, главная неприятность в том, что эти смещения могут полететь к чертям собачьим при последующих модификациях программы. Написал ты ассемблерный кусок, расчитал смещения, а затем решил добавить новый модуль в uses или просто добавил вызовы некоторых ранее не использовавшихся функций в существующих модулях. При этом компилятор может добавить куски кода как до твоего TWinControl.GetHandle, так и после, и твои hard-coded смещения могут оказаться инвалидными. Поэтому лучше или отказаться от этой затеи, или если хочется поизвращаться, то для надежности можно создать псевдо-таблицу адресов используемых методов. Использование таблицы со ссылками на св-ва будет гарантировать, что компилятор, во-первых, не выкинет при оптимизации неиспользуемые методы, во-вторых, при каждой компиляции будет обновлять адреса. Для функций без параметров, табличку можно сделать так: Код (Text): procedure PropertyTable_0; begin asm ret end; TForm(Nil).ControlCount; asm nop end; //выравнивание TForm(Nil).Handle; asm nop end; TForm(Nil).ClientHeight; asm nop end; TForm(Nil).ClientWidth; //... end; На асме это выглядит как массив qword'ов и старший dword есть смещение метода относительно адреса следующего qword'а Код (Text): 0042FC30 C3 retn 0042FC31 33C0 xor eax,eax 0042FC33 E8 84AEFEFF call TForm.ControlCount 0042FC38 90 nop 0042FC39 33C0 xor eax,eax 0042FC3B E8 48D2FEFF call TForm.GetHandle 0042FC40 90 nop 0042FC41 33C0 xor eax,eax 0042FC43 E8 E490FEFF call TForm.GetClientHeight 0042FC48 90 nop 0042FC49 33C0 xor EAX,EAX 0042FC4B E8 9890FEFF call TForm.GetClientWidth 0042FC50 C3 retn Соответсвенно в initialization модуля можно преобразовать относительные смещения в абсолютные адреса - или прямо в коде или скопировать в отдельный массив адресов ========================================== Вообще-то, все это попахивает извращениями. Наверное все таки проще миксить PAS и ASM вызовы Код (Text): asm ... end; MainForm.Handle; asm push eax ... end;
Способ вызвать статический (и не overload) метод: Код (Text): call TWinControl@GetHandle call TWinControl@GetControlCount call TObject@Free (В Delphi5, по крайней мере, работало)
BLOb С вызовом публичных статических методов проблем нет, можно и просто через точку вызывать call TObject.Free А вот с приватными облом - undeclared identifier PS: Кстати формально вызов св-ва типа mov eax,TForm.Handle тоже допустим, но при этом возвращается какое-то непонятное число - возможно какой-то ID или хэндл type information
leo А TWinControl.GetHandle и TWinControl.GetControlCount по-твоему публичные? В том и фишка, что так можно вызвать и приватный метод
BLOb call TWinControl@GetHandle действительно работает... Дельфя даже не слова не сказала!!! Все! Теперь замучаю ее... пасиба!!!
BLOb Действительно работает. Век живи, век учись ... ) PS: А я прокололся c TForm@GetHandle - undeclared identifier, т.е. наследование тут не рулит и нужно указывать именно тот класс, в котором объявлен private или protected метод. Например для наследуемого protected метода вызов TForm@GetParentWindow не проходит, хотя обычный вызов через точку TForm.GetParentWindow - без проблем