Int MessageBox
I
Начнем с того, как можно вызвать функции API. Обратимся к файлу помощи и выберем любую функцию API, например, MessageBox:
int MessageBox ( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );
Данная функция выводит на экран окно с сообщением и кнопкой (или кнопками) выхода. Смысл параметров: hWnd -дескриптор окна, в котором будет появляться окно-сообщение, lpText - текст, который будет появляться в окне, lpCaption - текст в заголовке окна, uType - тип окна, в частности можно определить количество кнопок выхода. Теперь о типах параметров. Все они в действительности 32-битные целые числа: HWND — 32-битное целое, LPCTSTR — 32-битный указатель на строку, UINT — 32-битное целое. По причине, о которой будет сказано ниже, к имени функций нам придется добавлять суффикс "А", кроме того, при использовании MASM необходимо также в конце имени добавить @16. Таким образом, вызов указанной функции будет выглядеть так: CALL MessageBoxA@16. А как же быть с параметрами? Их следует аккуратно поместить в стек. Запомните правило: СЛЕВА НАПРАВО — СНИЗУ ВВЕРХ. Итак, пусть дескриптор окна расположен по адресу HW, строки — по адресам STR1 и STR2, а тип окна-сообщения — это константа. Самый простой тип имеет значение 0 и называется МВ_ОК. Имеем следующее:
МВ_ОК equ 0 . . STR1 DB "Неверный ввод! ",0 STR2 DB "Сообщение об ошибке.",0 HW DWORD ? . . PUSH МВ_ОК PUSH OFFSET STR1 PUSH OFFSET STR2 PUSH HW CALL MessageBoxA@16
Как видите, все весьма просто и ничуть не сложнее, как если бы Вы вызывали эту функцию на Си или Delphi. Результат выполнения любой функции — это, как правило, целое число, которое возвращается в регистре EAX.
Аналогичным образом в ассемблере легко воспроизвести те или иные Си-структуры. Рассмотрим, например, структуру, определяющую системное сообщение:
typedef struct tagMSG { // msg HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG;
Это сообщение будет далее подробно прокомментировано в одном из примеров. На ассемблере эта структура будет иметь вид: