Delphi + basm

Тема в разделе "WASM.BEGINNERS", создана пользователем Ginger, 23 янв 2006.

  1. Ginger

    Ginger New Member

    Публикаций:
    0
    Регистрация:
    23 янв 2006
    Сообщения:
    8
    Такой вопрос... как мне в Дельфях (7) обратиться к свойству объекта на асме? Заранее спасибо
     
  2. Ginger

    Ginger New Member

    Публикаций:
    0
    Регистрация:
    23 янв 2006
    Сообщения:
    8
    Не ужели никто не знает? Или я не корректно описал вопрос?
     
  3. drmist

    drmist New Member

    Публикаций:
    0
    Регистрация:
    31 май 2005
    Сообщения:
    112
    Скорее Вы форумом ошиблись )



    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;





    Так подойдет?
     
  4. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Ginger

    Обратиться на паскале и почерпнуть ответ из дизассемблера.
     
  5. Ginger

    Ginger New Member

    Публикаций:
    0
    Регистрация:
    23 янв 2006
    Сообщения:
    8
    drmist- нет... это вызов простой API функции... а хотелось юы что-то типа

    mov eax, Form1.Handle

    Эт конечно не правильный вариант но смысл раскрывает...

    Quantum - я тож так думал... но я там запутался немного, поэтому и решил тут спросить...
     
  6. Ginger

    Ginger New Member

    Публикаций:
    0
    Регистрация:
    23 янв 2006
    Сообщения:
    8
    Quantum

    Решил послушаться Вашего совета и еще раз залесть в CPU...



    Delphi-код:
    Код (Text):
    1. mov eax, [ebp-$14]
    2. call TWinControl.GetHandle
    3. mov [ebp-$18], eax
    4.  




    Мой код:
    Код (Text):
    1. mov eax, MainForm
    2. call TWinControl.GetHandle
    3. push eax
    4.  


    Разница только в типе адресации к перемненным... ну еще у меня вместо пересылки результата в переменную, я ее в стек.

    Так вот, сама Дельфя ругается на call TWinControl.GetHandle в моем коде, т.к. функция все-таки приватная... говорит, что мол GetHandle ей не знаком... посоветуйте пожалуйста, как ЭТО обойти...
     
  7. drmist

    drmist New Member

    Публикаций:
    0
    Регистрация:
    31 май 2005
    Сообщения:
    112
    Ginger

    А кстати не факт, что это возможно.

    Да и маразм имхо - асм и дельфовские классы.
     
  8. Ginger

    Ginger New Member

    Публикаций:
    0
    Регистрация:
    23 янв 2006
    Сообщения:
    8
    - факт, что возможно...

    - не спорю... но все же..
     
  9. Sl4v4

    Sl4v4 New Member

    Публикаций:
    0
    Регистрация:
    18 окт 2005
    Сообщения:
    69
    Ой кошмар! К чему так извращаться-то?



    Написать процедуру/фунцию, из которой вызвать TWinControl.GetHandle, и вызвать её из асмовской вставки.
     
  10. Ginger

    Ginger New Member

    Публикаций:
    0
    Регистрация:
    23 янв 2006
    Сообщения:
    8
    Sl4v4

    Это понятно, но как быть, если мне нужны скажем свойства 30-40 классов VCL и не только... т.е. можно конечно продублировать исходные классы, наделать public-клонов функций - но это как Вы сказали
    .

    Ладна, всем пасиба за помощь... пойду писать реал-тайм генератор смещений фнкций в классах... пожелайте мне удачи
     
  11. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    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):
    1. procedure PropertyTable_0;
    2. begin
    3.   asm ret end;
    4.   TForm(Nil).ControlCount;
    5.   asm nop end;              //выравнивание
    6.   TForm(Nil).Handle;
    7.   asm nop end;
    8.   TForm(Nil).ClientHeight;
    9.   asm nop end;
    10.   TForm(Nil).ClientWidth;
    11.   //...
    12. end;
    На асме это выглядит как массив qword'ов и старший dword есть смещение метода относительно адреса следующего qword'а
    Код (Text):
    1. 0042FC30  C3            retn
    2. 0042FC31  33C0          xor  eax,eax
    3. 0042FC33  E8 84AEFEFF   call TForm.ControlCount
    4. 0042FC38  90            nop
    5. 0042FC39  33C0          xor  eax,eax
    6. 0042FC3B  E8 48D2FEFF   call TForm.GetHandle
    7. 0042FC40  90            nop
    8. 0042FC41  33C0          xor  eax,eax
    9. 0042FC43  E8 E490FEFF   call TForm.GetClientHeight
    10. 0042FC48  90            nop
    11. 0042FC49  33C0          xor  EAX,EAX
    12. 0042FC4B  E8 9890FEFF   call TForm.GetClientWidth
    13. 0042FC50  C3            retn
    Соответсвенно в initialization модуля можно преобразовать относительные смещения в абсолютные адреса - или прямо в коде или скопировать в отдельный массив адресов

    ==========================================

    Вообще-то, все это попахивает извращениями. Наверное все таки проще миксить PAS и ASM вызовы
    Код (Text):
    1.   asm
    2.     ...
    3.   end;
    4.   MainForm.Handle;
    5.   asm
    6.    push eax
    7.    ...
    8.   end;
     
  12. Ginger

    Ginger New Member

    Публикаций:
    0
    Регистрация:
    23 янв 2006
    Сообщения:
    8
    leo - Огроменное спасибо за ответ! Очень помог!
     
  13. BLOb

    BLOb New Member

    Публикаций:
    0
    Регистрация:
    20 апр 2004
    Сообщения:
    9
    Адрес:
    Russia
    Способ вызвать статический (и не overload) метод:
    Код (Text):
    1.  
    2.   call TWinControl@GetHandle
    3.   call TWinControl@GetControlCount
    4.   call TObject@Free
    5.  


    (В Delphi5, по крайней мере, работало)
     
  14. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    BLOb

    С вызовом публичных статических методов проблем нет, можно и просто через точку вызывать call TObject.Free

    А вот с приватными облом - undeclared identifier



    PS: Кстати формально вызов св-ва типа mov eax,TForm.Handle тоже допустим, но при этом возвращается какое-то непонятное число - возможно какой-то ID или хэндл type information
     
  15. BLOb

    BLOb New Member

    Публикаций:
    0
    Регистрация:
    20 апр 2004
    Сообщения:
    9
    Адрес:
    Russia
    leo

    А TWinControl.GetHandle и TWinControl.GetControlCount по-твоему публичные? :)

    В том и фишка, что так можно вызвать и приватный метод
     
  16. Ginger

    Ginger New Member

    Публикаций:
    0
    Регистрация:
    23 янв 2006
    Сообщения:
    8
    BLOb call TWinControl@GetHandle действительно работает... Дельфя даже не слова не сказала!!! Все! Теперь замучаю ее... пасиба!!!
     
  17. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    BLOb

    Действительно работает. Век живи, век учись ... :))



    PS: А я прокололся c TForm@GetHandle - undeclared identifier, т.е. наследование тут не рулит и нужно указывать именно тот класс, в котором объявлен private или protected метод. Например для наследуемого protected метода вызов TForm@GetParentWindow не проходит, хотя обычный вызов через точку TForm.GetParentWindow - без проблем