Delphi всемогущий Ms-Rem Хакер, номер #080, стр. 080-112-3 program Sample; begin end. После компиляции в Delphi 7 мы получаем экзешник размером в 13,5 Кб. Откуда?! Ведь в программе ничего нет! Ответ на этот вопрос опять поможет дать IDA. Дизассемблируем экзешник и посмотрим, что он содержит. Точка входа в программу будет выглядеть так: public start start: push ebp mov ebp, esp add esp, 0FFFFFFF0h mov eax, offset ModuleId call _InitExe ; здесь мог бы быть наш код call _HandleFinally CODE ends Весь лишний код находится в функциях _InitExe и _HandleFinally. Дело в том, что к каждой Delphi программе неявно подключается код, входящий в состав RTL (Run Time Library). Эта либа нужна для поддержки таких возможностей языка, как ООП, работа со строками (string) и специфичные для паскаля функции (AssignFile, ReadLn, WriteLn, etc.). InitExe выполняет инициализацию всего этого добра, а HandleFinally обеспечивает корректное освобождение ресурсов. Сделано это, опять же, для упрощения жизни программистам, и применение RTL иногда оправданно, так как может не понизить, а повысить эффективность кода. Например, в состав RTL входит менеджер кучи, который позволяет быстро выделять и освобождать маленькие блоки памяти. По своей эффективности он в три раза превосходит системный. В плане производительности генерируемого кода работа со строками реализована в RTL тоже довольно неплохо, правда все равно, в увеличении размера файла, RTL - виновник номер два после ООП. [уменьшаем размер] Если минимальный размер в 13,5 Кб тебя не устраивает, то будем убирать Delphi RTL. Весь код либы находится в двух файлах: System.pas и SysInit.pas. К сожалению, компилятор подключает их к программе в любом случае, поэтому единственное, что можно сделать, - удалить из этих модулей весь код, без которого программа может работать, и перекомпилить модули, а полученные DCU-файлы положить в папку с программой. Файл System.pas содержит основной код RTL и поддержки классов, но все это мы выбросим. Минимальное содержимое этого файла должно быть таким: unit System; interface procedure _HandleFinally; type TGUID = record D1: LongWord; D2: Word; D3: Word; D4: array [0..7] of Byte; end; PInitContext = ^TInitContext; TInitContext = record OuterContext: PInitContext; ExcFrame: Pointer; InitTable: pointer; InitCount: Integer; Module: pointer; DLLSaveEBP: Pointer; DLLSaveEBX: Pointer; DLLSaveESI: Pointer; DLLSaveEDI: Pointer; ExitProcessTLS: procedure; DLLInitState: Byte; end; implementation procedure _HandleFinally; asm end; end. Описания структуры TGUID компилятор требует в любом случае и без нее компилировать модуль отказывается. TInitContext понадобится линкеру, если мы будем собирать DLL. HandleFinally - процедура освобождения ресурсов RTL, компилятору она тоже необходима, хотя может быть пустой. |