Вопрос по работе с ассемблерным кодом, полученным от dcu2pas

Низкоуровневое программирование портов, микроконтроллеров и т.д.

Модератор: Andy

Ответить
Yuri K
Сообщения: 4
Зарегистрирован: 14 дек 2004, 18:59

Исходный текст на паскале такой:

procedure TPasswordDialog.EditChange(Sender: TObject);
var
HasText: Boolean;
begin
HasText := Edit.Text <> '';
AddButton.Enabled := HasText;
RemoveButton.Enabled := HasText;
OKButton.Enabled := HasText or PasswordAdded;
end;


Текст, выданный dcu2pas v1.3 выглядит так:

procedure TPasswordDialog.EditChange(Sender{Flag:$B, Type ID:$6, Offset:$1}: TObject); {Flag:$40, ID:$BBF8EAC, VProc:$4, Return TypeID:$D, Code offset:$108A, Size:$86}
var
HasText: Boolean; {Flag:$B, ID:$0, Type ID:$7, Offset:$3}
asm
@@0: {stack frame start}
@@3: push $00
@@5: push ebx
@@6: push esi
@@7: mov esi, eax
@@9: {try}
@@23: lea edx, [ebp-$04]
@@26: mov eax, [esi+$02FC]
@@32: call TControl.GetText
@@37: cmp dword ptr [ebp-$04], +$00
@@41: setnz bl
@@44: mov edx, ebx
@@46: mov eax, [esi+$0300]
@@52: mov ecx, [eax]
@@54: call dword ptr [ecx+$64]
@@57: mov edx, ebx
@@59: mov eax, [esi+$0304]
@@65: mov ecx, [eax]
@@67: call dword ptr [ecx+$64]
@@70: test bl, bl
@@72: jnz @@87
@@74: cmp byte ptr [esi+$0314], $00
@@81: jnz @@87
@@83: xor edx, edx
@@85: jmp @@89
@@87: mov dl, $01
@@89: mov eax, [esi+$030C]
@@95: mov ecx, [eax]
@@97: call dword ptr [ecx+$64]
@@100: {finally}
@@113: lea eax, [ebp-$04]
@@116: call System.@LStrClr
@@121: {end; finally}
@@129: pop esi
@@130: pop ebx
@@131: pop ecx
@@132: {stack frame end}
end;


Я так понимаю (правильно ли?), что конструкции вида
call dword ptr [ecx+$64]
относятся к вызову функции "SetEnabled".
По этой функции также выдаётся следующая информация

{Address defined in DBPWDlg.dcu:
...
22 TControl.SetAutoSize
23 TControl.SetDragMode
24 TControl.SetEnabled
...}

{Fixups defined in DBPWDlg.dcu:
...
29 E40 1 TControl.SetDragMode
2A E44 1 TControl.SetEnabled
2B E48 1 TCustomForm.SetParent
...}

Если бы не было исходного кода, то как воможно узнать, что конструкция call dword ptr [ecx+$64] относится к вызову функции TControl.SetEnabled?
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

По всей видимости SetEnabled виртуальная. Так что никак, если не знаешь таблицу виртуальных методов.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Yuri K
Сообщения: 4
Зарегистрирован: 14 дек 2004, 18:59

"никак, если не знаешь таблицу виртуальных методов."

call dword ptr [ecx+$64] - это смотрится по смещению в таблице в виртуальных методов?
А на предыдущий, следующий элемент в таблице, плюс сколько должно быть, с каким шагом там числа должны разниться?
В общем, если узнаем способ зачитать таблицу виртуальных методов (из dcu файлов, exe файла), то как дальше смотреть?
Andy
Сообщения: 238
Зарегистрирован: 17 фев 2004, 08:15
Откуда: Минск

Я так понимаю (правильно ли?), что конструкции вида
call dword ptr [ecx+$64]
относятся к вызову функции "SetEnabled".
Возможно. Можно кстати попробовать запустить этот код в отладчике типа "td32.exe" (в программе оставить отладочную информацию) и посмотреть что он там нарисует. А так... Ну чему, к примеру, равняется EAX в самом начале ассемблерного кода? - х/з. Пропущен кусок.
А на предыдущий, следующий элемент в таблице
Можно предположить, что это обычные четырехбайтные указатели. То есть для каждого следующего адреса функции +4 прибавлять.
*provided AS IS
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

А на предыдущий, следующий элемент в таблице, плюс сколько должно быть, с каким шагом там числа должны разниться?
DWORD alignment - стопудово :)
В общем, если узнаем способ зачитать таблицу виртуальных методов (из dcu файлов, exe файла), то как дальше смотреть?
Откуда это мы такой способ знаем? Это всё равно, что заявить: мы знаем, какое имя было у это локальной переменной. Эквивалентные изречения. Имя переменной не восстановить НИКОГДА по той причине, что везде в коде, где мы использовали её псевдоним компилятор поставил выражение [bp + ???] (локальные переменные располагаются в стеке). То же самое происходит в случае виртуальных функций. В ecx бросается адресс vitrual table, затем проиходит вызов [ecx + ???].
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Yuri K
Сообщения: 4
Зарегистрирован: 14 дек 2004, 18:59

"Откуда это мы такой способ знаем? Это всё равно, что заявить: мы знаем, какое имя было у это локальной переменной."

В exe, а тем более в dcu файлах можно найти имена VCL классов. Имена классов не пропадают. Каждому имени класса вроде бы строится своя виртуальная таблица, если не так, поправьте. Сорсы VCL посмотреть можно, какие виртуальные методы какой класс имеет, и соответственно можно посмотреть порядок следования этих методов в каждом из классов. Нужно в общем поизучать ситуацию.
Yuri K
Сообщения: 4
Зарегистрирован: 14 дек 2004, 18:59

"Ну чему, к примеру, равняется EAX в самом начале ассемблерного кода? - х/з. Пропущен кусок. "

А он разве один раз заполняется, этот регистр? Где это начало смотреть-то надо?
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

В exe, а тем более в dcu файлах можно найти имена VCL классов
Думаю, это справедливо только для Debug сборки.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить