Посмотрите внимательно на тело WinMain.
Посмотрите внимательно на тело WinMain. Там есть команда call, то есть вызов подпрограммы. А где, спрашивается, сама подпрограмма ExitProcess? Ан нету ее! А почему тогда, спрашивается, транслятор на это не ругается? А вы удалите строчку ExitProcess PROTO :DWORD и попробуйте оттранслировать свой исходник... Ага, хорошо знакомое: "undefined symbol : ExitProcess"? Еще бы, такой подпрограммы в нашем исходнике действительно нет!
Посмотрите на call ExitProcess - это вызов API'шной функции, завершающей работу нашей программы (виндозный аналог хорошо нам известного INT 20h). Именно подпрограмма с таким именем будет прилинкована к нашему экзешнику, и уж она-то знает способ, как ей обратиться к DLL-ке kernel32.dll и заставить ее прервать работу нашей программы! Еще раз повторюсь, прилинкуется не сама API'шная функция, а только подпрограммка, которая умеет эту внешнюю функцию вызывать.
Но это на этапе линковки, когда соединяются все "концы" между объектными файлами. А на этапе транслирования ассемблер не имеет никакого понятия о том, что в природе существует какой-то ExitProcess... И чтобы он (транслятор) не ругался, мол, "кто такой, почему не знаю", нужно их "познакомить" - при помощи так называемого прототипа. Другими словами, прототип - это своего рода уведомление транслятора о том, что "немного попозже я собираюсь обращаться к товарищу ExitProcess, и форма вызова для него такая-то". Ну а далее следуют "паспортные данные" на этого товарища - сколько он "переваривает" параметров, и какой они должны быть размерности, дабы тот, не дай бог, не подавился.
Вообще-то говоря, существует несколько способов подобного "уведомления", однако вышеприведенный, несмотря на свою кажущуюся навороченность, является самым эффективным, так как позволяет проверять соответствие количества и типа аргументов параметрам, тем самым помогая отслеживать целый ряд трудноуловимых ошибок.
Содержание раздела