Вопрос о минимальной программе для того или иного языка программирования и операционной среды обычно возникает в следующих случаях:
Между тем вопрос о минимальной программе - совсем не простейший, и представляет отнюдь не академический интерес. Минимальная программа, очевидно, решает две задачи: (1)стартует и (2)завершается в конкретной рабочей среде. И то, и другое она должна делать корректно, с тем, чтобы:
Здесь, пожалуй, уместно напомнить про ограниченность тематики сайта: прикладное программирование на masm под windows. Поэтому дальше речь пойдет не о программах вообще, и не о каких-нибудь VxD, а о приложениях, то бишь applications, непосредственно взаимодействующих с операционной системой.
Сказанное особенно важно для программ на ассемблере, который дает программисту абсолютную власть над компьютером, что, конечно же, подразумевает и абсолютную возможность напакостить. Чем выше язык программирования, тем более обставлены всяческим сервисом процессы запуска и завершения программы, тем более они безопасны, и тем меньше требований к соблюдению соответствующих ритуалов программистом.
В C/C++, например, запуск и завершение приложения win32 поддерживаются скрытой от прикладного программиста функцией _WinMainCRTStartup, содержащейся в runtime-библиотеке. Именно ее вызывает операционная система при запуске приложения, а уж она, кое-чего поделав, вызывает ту самую WinMain, с которой начинается всякое приложение, базирующееся на win32. (Конечно, строго говоря, запуск приложения посредством вызова _WinMainCRTStartup - это свойство не языка, а операционной среды.) От программиста же требуется, чтобы WinMain была правильно оформлена (включая четыре входных параметра), и завершалась оператором return с кодом выхода типа int.
В языках программирования более высокого уровня для программиста все еще проще, хотя там уже вряд ли можно говорить о том, что приложение-де "непосредственно взаимодействует с операционной системой". Java, еще более высокий, чем C/С++, уже не использует фиксированное название стартовой функции, да и завершение программы в нем - это просто закрывающая фигурная скобка.
Однако, вернемся к ассемблеру. Вот обещанный текст минимального приложения для win32:
.386 .model flat,stdcall ExitProcess PROTO :DWORD .code WinMain PROC PUBLIC hinst,prev_hinst,command_line,cmd_show ;... invoke ExitProcess,0 WinMain ENDP end
В результате компиляции и сборки этого приложения получается исполняемый файл размером 1536 байт. Из них собственно код занимает 10 байт. Все остальное - на совести создателей формата PE-файла. Приложение безропотно запускается и не задумываясь завершает свою работу, возвращая код выхода.
Что здесь что и зачем?
Замечание 1. По поводу необходимости применения функции ExitProcess. Именно с ее помощью, а не посредством команды ret, как могли бы ожидать знатоки C/C++, должно завершаться приложение win32, написанное на ассемблере.
Если залезть внутрь runtime-библиотеки C/C++, то мы увидим, что именно так завершает работу приложения уже упоминавшаяся функция _WinMainCRTStartup. Но поскольку подключать runtime-библиотеку C/C++ к ассемблерной программе как-то нелогично (хотя и вполне возможно), мы должны вызвать ExitProcess "вручную". Только эта функция корректно завершает работу приложения, в частности, оповещая использовавшиеся приложением библиотеки DLL о необходимости декрементировать их счетчики занятости и, при обнулении последних, выгрузиться из памяти.
Замечание 2. А вот и обещанная плохая новость про параметры стартовой процедуры. Дело в том, что установкой их значений занимается - кто бы вы думали? - опять же _WinMainCRTStartup! И следовательно, в ассемблерных программах, где ее нет, при входе в WinMain параметры содержат:
Так что, воленс-ноленс, придется получать эту ценную информацию самостоятельно. Как говорится, клик хере.
Замечание 3. И все-таки приведенный текст приложения - не самый минимальный. Можно сделать его еще меньше, для чего следует убрать все параметры функции WinMain. Поскольку приложение собирается без runtime-библиотеки C/C++, это вполне допустимо, так как больше не с чем выполнять ее связывание. В результате объем исполняемого файла останется тем же, а вот объем исполняемого кода в нем (образа приложения) сократится аж до 7 байт. Про это стоит почитать еще.
Замечание 4. В этой статье рассматривается минимизация размера кода программы, но отнюдь не exe-файла, ее содержащего. Как известно, исполняемые файлы Windows обычно имеют так называемый PE-формат, и манипуляции с этим форматом дают некоторые возможности для сокращения размера файла. Например, можно вместо стандартной stub-программы использовать более компактную, собственной разработки.
[C] Svet(R)off