Языки программирования

Assembler: программирование с помощью системных сообщений

Операционная система WINDOWS с самого начала своего существования была спроектирована как система для параллельного программирования. Разработчики WINDOWS начали идею клиент-серверного взаимодействия, которую положили в основу своей системы. Таким образом, в системе (в дальнейшем мы так будем называть общие свойства всех операционных систем WINDOWS) все процессы выполняют определенные действия для своих клиентов.

Тот процесс, который выполняет определенное действие называется сервером, а этот процесс, для которого выполняется действие, называется клиентом. Конечно, один программный модуль может быть одновременно и сервером, и клиентом. Клиент и сервер обмениваются сообщениями, или имеют общие блоки памяти. Ядро операционной системы состоит из множества файлов типа *. DLL (Dynamic Link Libraries), которые являются поставщиками определенных услуг для клиентов. Эти услуги доступны клиентам через так называемые функции API (Application Programming Interface). Каждый DLL-файл содержит определенное количество таких функций. При старте системы некоторые из этих файлов загружаются в память.

Если для выполнения программы необходима определенная функция API, которая находится в DLL-файле, который не был загружен, то инициатор программ загрузит нужный DLL-файл вместе с вашей программой. Количество функций API постоянно возрастает при переходе к новой версии, поэтому, если программа не использует прямых средств доступа к оборудованию, а пользуется лишь функциями API, то для таких программ обеспечивается совместимость снизу-вверх.

Среди функций API, которые чаще всего используются, есть функция SendMessageA, выделяющая так называемые сообщения в очередь любого процесса. Как правило, процессы получают сообщение из очереди с помощью функции GetMessageA. Понятие сообщение было введено разработчиками системы для того, чтобы обозначить запросы от клиентов, или события в системе, которые наиболее часто встречаются. Большинство сообщений для управления программными средствами ввода / вывода — окнами.

Исторически так сложилось, что программа и средства общения с ней были разделены. Когда программа создает окно, система вводит новый объект, который функционирует параллельно и независимо от программы, которая его создала. Этот объект называется «оконная процедура». Оконная процедура является сервером окна. Она выполняет все действия, которые заказывает процесс-клиент с помощью сообщений, каждое из которых запускает оконную процедуру с соответствующими параметрами при помощи функции DispatchMessage.

Для упрощения управления окнами их организуют в иерархическую структуру. Старшее окно называют родительским (parent), а младшее — дочерним (child). Специализированные окна называют контролем (Controls). Они имеют свои стандартизированные названия (классы) и являются дочерними окнами некоторого родительского окна, которое отвечает за ввод каких-либо параметров. Контролем можно управлять так же, как и обычными окнами — с помощью ICMP. Некоторые функции API для удобства дублируют возможности, которые предоставляет система сообщений.

Существуют также другие функции отправки сообщений, предназначенных для драйверов (SendDriverMessage) и функцией отправки сообщений в параллельных нитей-процессов (PostThreadMessageA). Сообщения, которые предназначены не для управления, а для информирования системы и других клиентов об определенных событиях, называются нотификацийнимы. Все нотификацийни сообщения от дочерних окон имеют код 4Eh и обозначаются названием WM_NOTIFY. Различаются они только параметрами wParam и lParam. Исключение составляет сообщение WM_COMMAND, поступающее от дочерних кнопок.

Следующий фундаментальный принцип программирования в системе WINDOWS — это стандартизация всех названий: событий, параметров, функций, сообщений и структур данных, независимо от языка и средств программирования в которых они используются. Такие стандарты существуют в виде специальных файлов, которые ставят в соответствие с любого названия определенную константу или шаблон структуры данных. Этими константами система пользуется на ассемблерном уровне программирования. Например, вызов произвольной функции API с N параметрами выглядит так:
Push
………………
Push <2-й параметр>
Push <1-й параметр>
Call <адрес функции>.