Я сейчас занимаюсь реверсированием кусков клиента lineage, и вот что я в нем увидел: 1) Из 5-6Гб примерно 30-40Мб кода, остальное - данные, потому с объемом сменив ЯВУ на асм ничего не сделать. 2) Несколько файлов накрыты фемидой (протектор), что увеличивает время загрузки на десятки секунд. При этом такая защита никак не мешает реверсированию, более того в неофициальных клиентов с нескольких файлов фемиду полностью сняли. 3) Код клиента написан на C++, который впрочем мало отличается от других ЯВУ. Неоптимальность кода достаточно велика, т.е. примерно половина инструкций лишние, большинство алгоритмических конструкций можно заменить более короткими и т.п. Например, типичная проблема компиляторов ЯВУ: mov [var1],reg1 mov reg1,[var1] такой код генерится на границе двух операторов var1=...; ...var1...; Далее проблемы операций с отдельными байтами: add ebx, 2 mov eax, ebx sar eax, 8 ; get BH byte mov byte ptr [esp+200Ch+send_packet_begin_size], bl mov byte ptr [esp+200Ch+send_packet_begin_size+1], al Неоптимизированные куски кода типа ___:004D2242 01C add esi, 4 ; Add ___:004D2245 01C add edi, 4 ; Add ___:004D2248 01C lea ebx, [ecx+eax] ; Load Effective Address ___:004D224B 01C add esi, 4 ; Add ___:004D224E 01C add edi, 4 Ну и много других проблем, в том числе использования stdcall там где подошел бы fastcall, использование [ebp+...] для обращения к локальным переменным там где можно использовать [esp+...], многочисленные лишние вызовы функций и прочее. Отдельно о коде делфи. Не знаю какой именно версии был компилятор, но он почти в каждой функции копировал параметры переданные по fastcall в локальные переменные и юзал уже их. Насчет неоптимальных конструкций - это скорее общая проблема и компилятора, и программиста. Это приводит к появлению конструкций ___:3000C9DC Put_@eax_DX proc near ___:3000C9DC 000 mov [eax], dx ___:3000C9DF 000 retn ; Return Near from Procedure ___:3000C9DF Put_@eax_DX endp ___:3000C9EC Put_@@eax_DX_Inc2_@eax proc near ___:3000C9EC 000 push ebx ___:3000C9ED 004 mov ebx, eax ___:3000C9EF 004 mov eax, [ebx] ___:3000C9F1 004 call Put_@eax_DX ; Call Procedure ___:3000C9F6 004 add dword ptr [ebx], 2 ; Add ___:3000C9F9 004 pop ebx ___:3000C9FA 000 retn ; Return Near from Procedure ___:3000C9FA Put_@@eax_DX_Inc2_@eax endp Также встречаются и такие конструкции: ___:30031AAD 004 add edx, -61h ; switch 26 cases ___:30031AB0 004 cmp edx, 19h ; Compare Two Operands ___:30031AB3 004 ja _end_case ; default ___:30031AB3 ; jumptable 30031AB9 cases 104-112,117,121 ___:30031AB9 004 jmp dword ptr _off_table[edx*4] ; switch jump ... set_0: xor eax, eax / jmp short _end_case set_1: mov eax, 1 / jmp short _end_case .... Очевидно, это стоило бы заменить на xlat или например на xor eax,eax /cmp edx, 19h-61h /ja @f /mov al,[_table-61h+edx] @@: Ну и напоследок, один занятный факт: в апи винды есть функция int ntohl(int), которая меняет местами байты в двойном слове. Эта функция полностью заменяется одной инструкцией процессора bswap.
Насчет удобства асма: есть фасм, у него есть свой препроцессор. Делаем макрос Код (Text): macro _call [line] { common match f(x),line \{ irp arg,x \\{reverse if arg eqtype "" call @f db arg,0 @@: else pushd arg end if \\} call [f] \} } И вместо invoke'а пишем _call CreateFileA("imp_log.txt",0x40000000,0,0,3,0,0) Добавляем macro _func [line]{match var=exp,line \{_call exp / mov var,eax \} } и пишем уже _func [hFile]=CreateFileA("imp_log.txt",0x40000000,0,0,3,0,0) Можно сделать и разбор такого кода: Код (Text): VAR ppDS8 IDirectSound8 hwnd dd ? BEGIN ;================================== HL DirectSoundCreate8(NULL,ppDS8,NULL) PRINTLN "IDirectSound8 @ 0x%08x", [ppDS8] H_ hwnd:=GetConsoleWindow HL ppDS8->SetCooperativeLevel([hwnd],DSSCL_PRIORITY) ...
GoldFinch Судя по приведеным кускам - код не оптимизирован. Дебуговская версия без инфы. При сильно кривом коде, бывает, оптимизировать не получается, а иногда включить забывают. Во всяк случ оптимизация в МСВС и ОВ такое, обычно, лечит. (даже проверил) class A{ int i; public: A(){ i = 0; }; int get(){ return i; } }; int main(){ A a; return a.get(); } === (msvc -O1) xor eax,eax ret
Да, она написана не на ассемблере, а на срр с асм-вставками. Вот вырезка из ридми: Да и системные требования не такие уж маленькие: Кстати, до сих пор интересно, как им удалось запихнуть ВСЕ в 96 килобайт. )
_basmp_, это код реального клиента, т.е. релиза. Думаю оптимизацию там включали. "call get /.../ get: xor eax,eax / ret" - разве это оптимально? "xor eax,eax" - вот это оптимально.
ответ очевиден))) писать на асме игру == изврат: скорость работы в основном определяется граф. подсистемой - вот если на асме написать аналог опенджиэль иль дх, то да - применение асма имеет смысл, но опять же сложности разработки, порты.
GoldFinch не знаю на чем это писано, но такая картина обычна для выключеной оптимизации. А не включать могли ибо клиент как всегда спешит, а некоторые хаки очень чувствительны к оптимизации. В каком виде отлаживали - в таком и сдавали. Игрушки вообще пишутся халтурно. Надежности и качества от них требуют редко. Разрабы - больше художники/сказочники. Ну и объем работы и без вылизывания кода неслабый. Интересно интересно. А из проги выйти как? xor eax,eax; ret; - 0 и выход. меньше не получится.
Там получается вся прога "EntryPoint:xor eax,eax; ret;" ? Тогда конечно да. А насчет "В каком виде отлаживали - в таком и сдавали. Игрушки вообще пишутся халтурно." - назовите большую прогу которая написана "не халтурно", и посмотрите ее код. Думаю там будет то же самое. алсо само использование "main()" вместо "start:" уже вызывает сомнения в оптимальности. букф в сорце больше.
GoldFinch Ну я бы не стал обобщать. Могу назвать целые системы сорцы которых читать просто приятно. С другой стороны попсовые, раскрученые проги, которые продадутся даже если будут одним сплошным глюком - то да, железо куется пока горячо. В такой ситуации главное побыстрее выпустить следующую версию с нумером старше чем у конкурентов и интерфейсом помультимедийнее (прог много, деньги одни). В линкере точку входа на _main и в конце main - ExitProcess. Ну еще /nodefaultlib итд.
_basmp_ несколько некорректное замечание. та же песня. --------------------------------------------------------------------------- надёжность - это обязательное усл., ибо в то, что вылетает каждые пять мин., никто играть не будет. качество? что именно вы имеете ввиду? насчёт слабой оптимизации алгосов - это действительно проблемма: физика мира, ИИ - сильно прожорливые штуки. на мой взгляд, разработчики ГТА весьма мощные ребята - например, сан андреас при всей развитости его мира, довольно "лёгкая" по ресурсоёмкости вещь. те же мост вонтед и карбон жрут ресурсов поболей, хотя уровни их миров реально ниже СА.
SmanxX1 В сети есть 40-минутный ролик, в котором они рассказывают как они этого добились. Очень интересно. Они имели 3 базовые текстуры и с пом. конечного числа преобразований, трансформаций и приёмов цветовой коррекции получали все остальные. Точно так же и с формами. Все creatures в игре вместе с их формой, анимацией и поведением занимают 6.3 кб благодаря очень интересному приёму. Вообще, они создали свой собственный инструмент для всего этого. Можно скачать здесь: http://www.scene.org:8080/dir.php?dir=%2Fparties%2F2004%2Fassembly04%2Fassemblytv%2Fseminars/ GoldFinch По одной неизвестно как скомпилированной и написанной программе судить о избыточности и неоптимальности выдаваемого компилятором кода, по-меньшей мере, неверно. Если хочешь делать выводы, приведи пример кода на С/С++, когда компилятор создаёт неоптимальный код. Во-вторых, современные компиляторы проводят многоуровневую оптимизацию, ты же говоришь только об оптимизации буквально на уровне инструкций. По статистике, 95% времени исполнения программы приходится на 4% кода. Помнится пару лет назад здесь была тема, где спорили "человек vs компилятор", где мнения разделились. Я тогда, в силу своей неопытности в ЯВУ, считал, что человек может писать на ассемблере более оптимальный код. Сейчас я другого мнения и изменил его в процессе использования современных С/С++ компиляторов.
W4FhLF Проще говоря программы писать на асме есть идиотизм и лучше юзать C/C++ со множеством вставок асма а потом все это дело оптимайзить? Тогда наверно знание самого асемблера помогает только в том случае, когда тебе нужно избижать (править exe, dll) ошибки в программе постоянно выскакивающие или же kpяk писать?
SmanxX1 Очень впечетляет. В пору времени когда я пытался писать игрушку (безуспешно=)) подобного я найти не мог. Были примеры. Но чтоб весили как эта написаная на сях + вставки асма. З.Ы.: Кстати требования полная фигня за исключением оперативы Оо - это куда столько? А графика в самом первом ролике смею предположить не хуже Half-Life первого =))
D3s Зачем вставки? Оптимизация не ограничивается выкраиванием нескольких тактов переписываем кода на ассемблер. Что ты теряешь, когда вставляешь асм-вставку? Читабельность, гибкость, переносимость, соответствие стандарту. Что ты приобретаешь? Более высокую скорость исполнения? Насколько высокую? На порядок? Если да и если данный код критичен к скорости выполнения и если небыло других вариантов оптимизации, то использование асм-вставки считаю оправданным. Но это очень нежелательно. При современном положении дел есть области, где знание ассемблера обязательно, но это очень узкоспециализированные задачи, в остальном же ассемблер -- это скорее вспомогательные знания, которые являются безусловным плюсом. Если ты желаешь стать программистом в будущем, я тебе советую просто смотреть на мир шире. Быть гибким. Если сейчас тебе доставляет удовольствие программирование не ассемблере, то занимайся этим, не вижу ничего плохого. Просто постепенно, когда перед тобой возникают реальные задачи, не хочется зацикливаться на технических деталях. Вот, например, задача распознавания текста. Я могу написать её решение на ассемблере, но в процессе мне слишком часто придётся отвлекаться на технические детали, отладку, кучу однотипного рода мелких задач. Хочется абстрагироваться от этих деталей, сосредоточиться на решении задачи как таковой. Например, в MathCad'e я построил мат. модель задачи за короткое время, оперируя реальными сущностями(объект изображение, словарь признаков, алфавит эталонных классов, фильтр), а не байтами, вордами, двордами.
А вот некоторые мои знакомые или просто товарищи говорят мне следующее: тебе это не нужно, ты занимаешся херней и т.п.(в смысле не только изучая асм а и делфи и си) Я уже начал задумыватся, ведь программированию я уделяю 50-60% своего свободного времени, в тот момент когда мои ровестники ищут себе жену. Становиться страшно когда подумаеш каким ты будеш к 25-27 годам xD. Как бы совместить програминг и реал =)) У меня еще вопрос. Сейчас почти дочитал до конца http://wasm.ru/article.php?article=1022001 вот эту статью и уже хочу продолжения =), не знаете автор писал еще статьи (не обязательно на этом сайте)?
W4FhLF Спасиб, посмотрю. Про текстуры и пр. я знал, но даже при таком расскладе, лично я бы не смог уложиться и в 200 кб. xDDD D3s Для начала 2004 года -- это не фигня.