Страница 1 из 1

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

Добавлено: 14 дек 2004, 19:06
Yuri K
Исходный текст на паскале такой:

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?

Добавлено: 14 дек 2004, 19:18
Romeo
По всей видимости SetEnabled виртуальная. Так что никак, если не знаешь таблицу виртуальных методов.

Добавлено: 14 дек 2004, 20:05
Yuri K
"никак, если не знаешь таблицу виртуальных методов."

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

Добавлено: 14 дек 2004, 21:09
Andy
Я так понимаю (правильно ли?), что конструкции вида
call dword ptr [ecx+$64]
относятся к вызову функции "SetEnabled".
Возможно. Можно кстати попробовать запустить этот код в отладчике типа "td32.exe" (в программе оставить отладочную информацию) и посмотреть что он там нарисует. А так... Ну чему, к примеру, равняется EAX в самом начале ассемблерного кода? - х/з. Пропущен кусок.
А на предыдущий, следующий элемент в таблице
Можно предположить, что это обычные четырехбайтные указатели. То есть для каждого следующего адреса функции +4 прибавлять.

Добавлено: 15 дек 2004, 11:21
Romeo
А на предыдущий, следующий элемент в таблице, плюс сколько должно быть, с каким шагом там числа должны разниться?
DWORD alignment - стопудово :)
В общем, если узнаем способ зачитать таблицу виртуальных методов (из dcu файлов, exe файла), то как дальше смотреть?
Откуда это мы такой способ знаем? Это всё равно, что заявить: мы знаем, какое имя было у это локальной переменной. Эквивалентные изречения. Имя переменной не восстановить НИКОГДА по той причине, что везде в коде, где мы использовали её псевдоним компилятор поставил выражение [bp + ???] (локальные переменные располагаются в стеке). То же самое происходит в случае виртуальных функций. В ecx бросается адресс vitrual table, затем проиходит вызов [ecx + ???].

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

В exe, а тем более в dcu файлах можно найти имена VCL классов. Имена классов не пропадают. Каждому имени класса вроде бы строится своя виртуальная таблица, если не так, поправьте. Сорсы VCL посмотреть можно, какие виртуальные методы какой класс имеет, и соответственно можно посмотреть порядок следования этих методов в каждом из классов. Нужно в общем поизучать ситуацию.

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

А он разве один раз заполняется, этот регистр? Где это начало смотреть-то надо?

Добавлено: 15 дек 2004, 14:33
Romeo
В exe, а тем более в dcu файлах можно найти имена VCL классов
Думаю, это справедливо только для Debug сборки.