- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
// Получение имени выполняемого метода, вызывать можно только из Published-методов класса.
// Для обычных методов: FindClassMethodNames(ClassType()), для статических методов FindClassMethodNames(self).
{$optimization OFF}
function FindClassMethodNames(obj: TClass): string;
var _AdrPtr: Pointer;
begin
asm
mov eax, obj
mov edx, dword ptr [esp + 272]
push ebx
push esi
push edi
push $7FFFFFFF
xor edi, edi
jmp @@haveVMT
@@outer:
mov eax, dword ptr [eax]
@@haveVMT:
mov esi, dword ptr [eax].vmtMethodTable
test esi, esi
je @@parent
movzx ecx, word ptr [esi]
add esi, 2
@@inner:
pop ebx
push edx
sub edx, dword ptr [esi + 2]
jl @@no1
cmp edx, ebx
jg @@no1
mov ebx, edx
mov edx, dword ptr [esi + 2]
mov edi, edx
@@no1:
pop edx
push ebx
movzx ebx, word ptr [esi]
add esi, ebx
dec ecx
jnz @@inner
@@parent:
mov eax, dword ptr [eax].vmtParent
test eax, eax
jne @@outer
mov _AdrPtr, edi
pop edi
pop esi
pop ebx
end;
Result := obj.MethodName(_AdrPtr);
end;
{$optimization ON}
// пример использования
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(FindClassMethodNames(ClassType()));
end;
А есть нормальный способ получить имя выполняемого метода, и строку кода заодно?
bormand 11.07.2012 11:04 # +4
Fai 11.07.2012 11:35 # 0
defecate-plusplus 11.07.2012 11:45 # 0
шаблоенэрики в дельфи-7
bormand 11.07.2012 14:15 # 0
ctm 11.07.2012 14:36 # −1
defecate-plusplus 11.07.2012 14:41 # +2
bormand 11.07.2012 15:50 # 0
ctm 12.07.2012 05:43 # 0
TarasB 11.07.2012 11:48 # 0
Думаю, если переписать это с кулхацкерского языка на нормальный, то будет проще.
ctm 11.07.2012 12:14 # +3
HaskellGovno 11.07.2012 17:15 # +2
Выключили и без того слабую оптимизацию?
А на ассемблере небось писали для оптимизации?
Эпично.
bormand 11.07.2012 20:05 # 0
TarasB 11.07.2012 20:39 # +3
bormand 11.07.2012 21:17 # +2
Здесь gcc подберет удобные для окружающего кода регистры, и подставит их имена вместо %0 и %1. В какой-то степени это можно назвать оптимизацией...
eth0 11.07.2012 21:54 # 0
Т.е., оно, конечно, сейчас называется GAS в некоторых мануалах. Но исторически это кое-что другое.
bormand 11.07.2012 22:06 # 0
TarasB 12.07.2012 09:36 # 0
bormand 12.07.2012 10:21 # +2
Вкратце:
TarasB 12.07.2012 10:57 # +1
Fai 12.07.2012 12:18 # +6
bormand 12.07.2012 12:27 # 0
Fai 12.07.2012 13:07 # +1
mov eax, myVar <- загружаем адрес myVar
mov eax, [myVar] <- загружаем значение по адресу myVar
mov eax, [myVar+1] <- КО: загружаем значение по адресу myVar + 1
Никаких MASM'овских OFFSET не нужно.
quest 12.07.2012 13:11 # +1
lea eax, [eax*8+ebx+9000]
?
bormand 12.07.2012 13:15 # +1
LightBlack 11.07.2012 20:49 # 0
TarasB 11.07.2012 20:38 # 0
Нормальная там оптимизация, если знать, что оптимизируется, а что - нет. Запарили этим стереотипом.
>{$optimization OFF}
Я так понимаю, это для того, чтобы гарантировать наличиа адреса возврата и указателя на строку на том месте, на котором их ждут - чтобы оптимизатор их не выкинул. Правда я не понимаю, как локалное отключиние оптимизации поможет компилятору догадаться, какие именно строки не надо выкидывать.
LightBlack 11.07.2012 20:46 # 0
ctm 12.07.2012 05:54 # 0
да и в TObject все реализовано подобным способом.
оптимизация отключена, т.к. иначе оно что-то со стеком делает
LightBlack 11.07.2012 20:52 # 0
Штоу?
ctm 12.07.2012 05:56 # 0
bormand 11.07.2012 21:20 # 0
Кстати, а чего-то типа сишных __FILE__ __LINE__ и __FUNCTION__ в делфи нет?
bormand 11.07.2012 21:29 # +3
defecate-plusplus 11.07.2012 21:59 # +6
так что не надо тут клеветы
Fai 12.07.2012 08:11 # 0
TarasB 12.07.2012 09:38 # 0
guest 13.07.2012 14:27 # +1
defecate-plusplus 13.07.2012 14:33 # 0
просто вывести в лог и продолжить работу, например?
guest 13.07.2012 16:55 # +1
defecate-plusplus 13.07.2012 17:19 # 0
я правильно понял, что только путем выкидывания и отлова на месте EAssertionFailed?
guest 13.07.2012 17:29 # +1
А для других целей - нету нормального метода, можно с ассемблером извращаться, можно строку EAssertionFailed парсить. И то и то - на любителя. В С вот нет нормального метода получить текст текущей процедуры.
defecate-plusplus 13.07.2012 17:51 # +2
компилятору виднее всех в каком файле, в какой строчке и в какой функции он сейчас транслирует код, поэтому замена __FILE__, __LINE__, __FUNCTION__ и других базовых фич на "давайте выкинем исключение, всё равно это ведь только для фатальных ситуаций надо", только лишь потому что компилятор этого не умеет - не только для фатальных
и да, что такое текст текущей процедуры? это же не интерпретатор
TarasB 13.07.2012 18:08 # +4
Только для функций, помеченных словом logged. Как правило надо только несколько функций проверить, то есть проще написать, какие надо логгировать, чем какие не надо.
В отличие от классического отладчика, не надо будет думать "ой бля что только что в этой переменной было, как назад отмотать". Одни преимущества.
bormand 13.07.2012 18:37 # 0
Так?
http://ideone.com/OzEWX
TarasB 13.07.2012 18:40 # 0
bormand 13.07.2012 18:45 # 0
bormand 13.07.2012 18:57 # 0
http://ideone.com/LkNKA
bormand 13.07.2012 19:07 # 0
http://ideone.com/tq9bJ
TarasB 13.07.2012 19:59 # 0
И *- это типа раскрывател скобок такой, чтобы f(*(1,2)) перевести в f(1,2)?
roman-kashitsyn 13.07.2012 20:52 # 0
Да Это просто мега-полезная фича
bormand 14.07.2012 05:07 # +1
А вот это, увы, никак.
Vindicar 13.07.2012 21:34 # 0
Интересно, я думаю в Си тоже можно что-то типа такого реализовать.
P.S.: Чорд, вот что значит полениться перейти по ссылке.
TarasB 13.07.2012 21:47 # 0
roman-kashitsyn 14.07.2012 16:30 # 0