Delphi всемогущий Ms-Rem Хакер, номер #080, стр. 080-112-4 Теперь урежем файл SysInit.pas, который содержит код инициализации и завершения работы RTL и управляет поддержкой пакетов. Нам хватит следующего: unit SysInit; interface procedure _InitExe; procedure _halt0; procedure _InitLib(Context: PInitContext); var ModuleIsLib: Boolean; TlsIndex: Integer = -1; TlsLast: Byte; const PtrToNil: Pointer = nil; implementation procedure _InitLib(Context: PInitContext); asm end; procedure _InitExe; asm end; procedure _halt0; asm end; end. InitExe - процедура инициализации RTL для EXE-файлов, InitLib - для DLL, halt0 - завершение работы программы. Все остальные лишние структуры и переменные, которые пришлось оставить, необходимы компилятору. Они не будут включаться в выходной файл и никак не повлияют на его размер. Теперь положим эти два файла в папку с проектом и скомпилируем их из командной строки: dcc32.exe -Q system.pas sysinit.pas -M -Y -Z -$D- -O Избавившись от RTL, мы получили экзешник размером в 3,5 Кб. Борландовский линкер создает в исполняемом файле шесть секций, они выравниваются по 512 байт, к ним плюсуется PE-заголовок, что и дает эти 3,5 Кб. Но вдобавок к малому размеру мы получаем и определенные затруднения, так как теперь не сможем использовать заголовочные файлы на WinAPI, идущие с Delphi. Вместо них придется писать свои. Это нетрудно, поскольку описания используемых API можно брать из борландовских хедеров и переносить в свои по мере необходимости. Если в составе проекта есть несколько PAS-файлов, линкер для выравнивания кода вставит в него пустые участки, и размеры опять увеличатся. Чтобы этого избежать, нужно всю программу, включая определения API, помещать в один файл. Это весьма неудобно, поэтому лучше воспользоваться директивой препроцессора $INCLUDE и разнести код на несколько inc-файлов. Тут может встретиться еще одна проблема - повторяющийся код (когда несколько inc-файлов подключают один и тот же inc) компилятор в таких случаях компилировать откажется. Выйти из положения можно, воспользовавшись директивами условной компиляции, после чего любой inc-файл будет иметь вид: {$ifndef win32api} {$define win32api} // здесь идет наш код {$endif} Таким образом, можно писать без RTL достаточно сложные программы и забыть о неудобствах. [можно еще меньше!] Наверняка минимальный размер экзешника в 3,5 Кб удовлетворит не всех. Что ж, если постараться, можно ужать его еще в несколько раз. Для этого нужно отказаться от удобств работы с борландовским линкером и собирать исполнимые файлы линкером от Microsoft. К сожалению, здесь нас ждет одна загвоздка. Мелкософтовский линкер использует в качестве основного рабочего формата COFF, но может понимать и интеловский OMF. Однако программисты Борланда (видать, нарочно) в версиях Delphi выше третьей изменили генерируемый формат obj-файлов так, что теперь он несовместим с Intel OMF. То есть теперь существуют два вида OMF: Intel OMF и Borland OMF. Программы, способной конвертировать объектные файлы из формата Borland OMF в COFF или Intel OMF, я не нашел. Поэтому придется использовать компилятор от Delphi 3, который генерирует стандартный объектный файл Intel OMF. Импорт используемых API нам тоже придется описывать вручную, причем достаточно необычным способом. Для начала возьмем библиотеку импорта user32.lib из состава Visual C++ и откроем ее в HEX-редакторе. Имена функций в ней имеют вид "_MessageBoxA@16", где после @ идет размер передаваемых параметров. Следовательно, объявлять функции мы будем таким образом: |