В первой статье мы получили представление о строении машинных инструкций. Во второй статье научились составлять с использованием подручных средств файлы любого уровня сложности. Наконец, в прошлой статье начали создавать исполняемые файлы, которые система "признает" в качестве своих. Теперь мы вплотную стоим перед дверями, открывающими доступ к неисчислимым сокровищам мира Windows.
Это API - Application Programming Interface - интерфейс прикладного программирования, огромная библиотека уже готовых наборов инструкций, входящая в состав самой системы и служащая для выполнения разнообразнейших задач почти на все случаи жизни - имеется в виду, жизни в мире Windows :).
Сокровища эти упакованы в виде процедур и функций и размещены в системных модулях - dll. Чтобы получить к ним доступ, необходимо связаться с соответствующими модулями и импортировать из них нужные нам функции. Попробуем сегодня создать элементарное приложение, выводящее простое сообщение с набранным нами текстом и на этом завершающее свою работу. Эту работу осуществляет функция MessageBoxA, находящаяся в модуле User32.dll. Чтобы не пришлось "прибивать" наше приложение из менеджера задач, как в прошлый раз, оно должно также содержать для своего нормального завершения вызов функции ExitProcess из модуля Kernel32.dll.
Обычно для своей работы эти системные функции используют какие-то наши данные, которые мы им должны передать в виде параметров. Например, функции MessageBoxA мы должны предоставить текст, который хотим отобразить. В первой статье мы рассматривали инструкции, позволяющие копировать данные из одного места в другое. Однако, в данном случае мы ничего не знаем о внутреннем "устройстве" вызываемых функций и о том, в каком месте они хранят данные, с которыми работают. Как раз для подобных случаев был изобретен в свое время механизм, получивший название стека.
Стек - это некоторая область в виртуальном адресном пространстве процесса, специально предназначенная для временного хранения данных. Если помните, при создании PE-заголовка мы заполняли поля с размером выделяемого стека. Место, где разместить стек, выбирает система, а соответствующий адрес памяти сохраняет в регистре ESP. Этот регистр специально предназначен для работы со стеком и поэтому не должен использоваться ни для каких других данных.