Потребовалось недавно проанализировать одну DLL. Нужно было найти какие биты устанавливаются/сбрасываются при управлении конкретным USB-устройством. Исходный текст (cpp) и документация были недоступны, но поскольку данная DLL была небольшая – дисассемблировали ее и довольно быстро все нашли.
Но какой же говкокод там во всех операторах!
Вот типичный пример:
PUSH EBP
MOV EBP,ESP
PUSH ECX
MOV [EBP]-4,ECX
MOV ECX,[EBP]-4
ADD ECX,0000000C
CALL 100188A0
MOV ESP,EBP
POP EBP
RET
И после этого утверждают, что трансляторы программируют лучше человека? Не задумываясь, программист написал бы весь этот фрагмент двумя командами:
ADD ECX,0000000C
JMP 100188A0
Или вот картиночка, достойная пера:
…
FST32P [EBP]-0C
FLD32 [EBP]-0C
MOV ESP,EBP
POP EBP
RET
Здесь извлекается из FPU результат в локальную переменную, которая двумя строками ниже уничтожается. Но ничего страшного, командой FLD, следующей сразу за FST, статус-кво восстанавливается и в FPU опять загружается только что выгруженное значение. После такой толчеи воды в ступе состояние системы остается прежним. Прекрасно с точки зрения производительности!
Ну и наконец, вишенка на тортике.
Вот тот самый найденный фрагмент, устанавливающий и сбрасывающий биты в управляющем слове:
…
MOV EDX,[EBP]+FFFFFFEC
OR EDX,00000001
MOV [EBP]+FFFFFFEC,EDX
MOV EAX,[EBP]+FFFFFFEC
AND EAX,FFFFFFFD
MOV [EBP]+FFFFFFEC,EAX
MOV ECX,[EBP]+FFFFFFEC
AND ECX,FFFFFFFB
MOV [EBP]+FFFFFFEC,ECX
MOV EDX,[EBP]+FFFFFFEC
AND EDX,FFFFFFF7
MOV [EBP]+FFFFFFEC,EDX
MOV EAX,[EBP]+FFFFFFEC
AND EAX,FFFFFFCF
MOV [EBP]+FFFFFFEC,EAX
MOV ECX,[EBP]+FFFFFFEC
AND ECX,FFFFFFBF
MOV [EBP]+FFFFFFEC,ECX
MOV EDX,[EBP]+FFFFFFEC
AND EDX,FFFFFF7F
MOV [EBP]+FFFFFFEC,EDX
MOV EAX,[EBP]+FFFFFFEC
AND EAX,FFFFFBFF
MOV [EBP]+FFFFFFEC,EAX
MOV ECX,[EBP]+FFFFFFEC
AND ECX,FFFFF7FF
MOV [EBP]+FFFFFFEC,ECX
MOV EDX,[EBP]+FFFFFFEC
AND EDX,FFFFCFFF
MOV [EBP]+FFFFFFEC,EDX
MOV EAX,[EBP]+FFFFFFEC
AND EAX,FFFFBFFF
MOV [EBP]+FFFFFFEC,EAX
MOV ECX,[EBP]+FFFFFFEC
AND ECX,FFFFFDFF
MOV [EBP]+FFFFFFEC,ECX
MOV EDX,[EBP]+FFFFFFEC
AND EDX,FFFFFEFF
MOV [EBP]+FFFFFFEC,EDX
…
Шикарный код! Напоминает работу машины Тьюринга, не правда ли?
Не то, что жалкий код типа,
AND D PTR [EBP]+FFFFFFEC,1111 1111 1111 1111 1000 0000 0000 0001
OR D PTR [EBP]+FFFFFFEC,1
Который, правда, делает то же самое. Здесь, уже не только транслятор виноват, но и отсутствие нормальных битовых строк. В некоторых языках (не будем указывать пальцем в каких) это делается не операторами сдвига, а напрямую:
X=X &’1111 1111 1111 1111 1000 0000 0000 0001’B ! ’1’B;
И подобных мест полно в обычной программе, оттранслированной обычными средствами.
Так что, что бы вы ни делали, в ваших программах всегда полно говнокода.
А где же оптимизатор? Сразу на ум приходит Герцог из к/ф «Тот самый Мюнхгаузен» со своим вопросом: «А где же командующий?». Ответ, помнится, был – «командует». Так и здесь ответ: «оптимизирует»