Техническая поддержка :

Современные решения

для защиты Windows программ

и восстановления исходного кода
Автор: xen. Дата публикации: 10.08.2004

Создание окна MessageBox на Ассемблере



Прочитав эту статью Вы научитесь создавать нормальное Windows-приложение, отображающее окно сообщения (messagebox) с текстом: "Программировать на Ассемблере под Win32 очень просто!".
Windows cодержит очень много ресурсов для программ. Центральное место в них занимает Win32 API. Windows API это набор очень полезных и готовых к использованию любой программой функций, расположенных внутри Windows и функционально объединенных в DLL-файлах, таких как Kernel32.dll, User32.dll и Gdi32.dll. Kernel32.dll содержит API-функции, работающие с памятью и управляющие процессами. User32.dll управляет интерфейсом Вашей программы. Gdi32.dll содержит графические функции. Кроме трех основных существуют и другие библиотеки, информация о них вам также доступна.

Windows-приложение динамически связано с dll-файлами, т.е. код API-функции не включается в исполняемый файл, в это место помещается команда безусловного перехода в то место соответствующей библиотеки, где находится данная функция. Для того, чтобы Ваша программа смогла найти необходимые API-функции в процессе работы, Вы должны включить некоторую информацию в .exe файл. Необходимая информация находится в библиотечных импортируемых функций. Вы должны связать свою программу с верной библиотекой импортируемых функций, иначе она не сможет найти необходимую функцию.

Существует два типа API-функций: ANSI и Unicode. Имена ANSI функций оканчиваются символом "А", например MessageBoxA. Имена Unicode функций оканчивается символом "W" (Wide char), например MessageBoxW. Windows 95 в основном использует ANSI функции, Windows NT - Unicode.

Чаще всего, Вы будете использовать включаемый файл, который в зависимости от платформы позволит определить, какой тип API-функций написать. Поэтому, в своей программе используйте имена функций без окончаний "А" и "W", например MessageBox.

Я хотел бы привести структуру всех Windows-приложений:

CODE NOW!

.386
.model flat, stdcall
.data
.code
Main:
end Main




А теперь давайте попытаемся постепенно заполнить ее остальными необходимыми строками.

Любое Windows-приложение должно вызывать API-функцию ExitProcess для завершения программы. В заголовочном файле языка Си winbase.h мы можем видеть следующий прототип этой функции:

CODE NOW!

void WINAPI ExitProcess(UINT uExitCode);




Тип void означает, что функция ничего не возвращает. WINAPI означает использование способа передачи аргументов в функцию - stdcall. UINT - тип данных, беззнаковое целое число, разрядностью 32-бит. uExitCode - значение, передаваемое в Windows после завершения программы. Это значение в Windows не используется.

Чтобы вызвать ExitProcess из программы на Ассемблере, Вы должны определить ее прототип:

CODE NOW!

.386
.model flat, stdcall
ExitProcess PROTO ,:DWORD
.data
.code
Main:
INVOKE ExitProcess, 0
end Main




Это Ваше первое Windows-приложение. Сохраните его в файле msgbox.asm. Затем попробуйте ассемблировать этот файл с помощью программы-ассемблера ml.exe (удостовертесь в наличии пути к этому файлу в Вашем autoexec.bat) с помощью следующей строки:

ml.exe /c /coff /Cp msgbox.asm

/c сообщает MASM, что необходимо только ассемблировать файл, не производя линковку с помощью link.exe
/coff сообщает MASM, что файлы с расширением .obj должны создаватся в формате COFF
/Cp сообщает MASM, что он должен различать в файле строчные и прописные буквы (в именах функций, переменных и т.д.)

После этого произведем линковку (связывание) Вашего приложения с помощью команды link.exe:

link /SUBSYSTEM:WINDOWS /LIBPATH:c:\masm611\lib msgbox.obj kernel32.lib

/SUBSYSTEM:WINDOWS сообщает Link, о типе создаваемого .exe файла
/LIBPATH: сообщает Link, где находятся библиотеки импортируемых функций. На моем компьютере это c:\masm611\lib

Ассемблирование и линковка вместе называются компиляцией.

Итак, мы получили приложение msgbox.ехе. Пробуем его запустить... но ничего не происходит. Не волнуйтесь, единственное, что пока делает наше приложение - закрывается после старта. Но все-таки это нормальное Windows-приложение. Обратите внимание на размер ехе-файла - 1,536 байт!

Вы определяете функцию с помощью следующей строки:

CODE NOW!

ExitProcess PROTO, :DWORD,




а потом записываете список типов параметров функции. MASM использует прототип функции для проверки количества и типа параметров, передаваемых функцию. Лучшим местом для прототипов функций является включаемый файл (include file). Вы можете поместить в этот файл описание части используемых функций и структур данных и включаете его в начале вашей программы на Ассемблере.

Вызов функции в программе осуществляется с помощью ключевого словa INVOKE:
CODE NOW!


INVOKE ExitProcess, 0




INVOKE является особым типом вызова функции. При его использовании проверяется количество и тип передаваемых аргументов, и они передаются в стек согласно выбранному по умолчанию способу вызова функций (в нашем случае используется stdcall). Используя INVOKE вместо обычного вызова, вы освободитесь от стековых ошибок при неверной передаче аргументов. Это очень удобно!

Для создания окна сообщения используется фукнция MessageBoxA. Определение этой функции выглядит следующим образом:

int WINAPI MessageBoxA(HWND hwnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType),

где hwnd - указатель на родительское окно
lpText - указатель на строку текста, который Вы хотите вывести в области отображения окна сообщения
lpCaption - указатель на текст заголовка окна сообщения
uType определяет тип иконки, а также количество и вид кнопок в окне сообщения

В Win32 HWND, LPCSTR и UINT имеют разрядность 32 бит.

Давайте изменим файл msgbox.asm включив в него вызов функции MessageBoxA:

CODE NOW!

.386
.model flat, stdcall
ExitProcess PROTO ,:DWORD
MessageBoxA PROTO ,:DWORD, :DWORD, :DWORD, :DWORD
.data
MsgBoxCaption db "Пример окна сообщения",0
MsgBoxText db "Программировать на Ассемблере под Win32 очень просто!",0
.const
NULL equ 0
MB_OK equ 0
.code
Main:
INVOKE MessageBoxA, NULL, ADDR MsgBoxText, ADDR MsgBoxCaption, MB_OK
INVOKE ExitProcess, NULL
end Main




Скомпилируйте программу, как мы это уже сделали выше. Но в данном случае при линковке необходимо в конце строки добавить user32.lib, т.к. описание функции MessageBoxA находится именно в этом файле. После компиляции, запустите программу - Вы увидите окно сообщения с текстом "Программировать на Ассемблере под Win32 очень просто!".

Вернемся опять к исходному тексту программы. В секции .data мы определили две строки, закрытые нулем. Запомните: в Windows все строки должны быть закрыты нулем (двоичным, т.е. числом 0, а не символом "0"). В секции .const мы определили две константы. Мы использовали константы для большей понятности программы (константа MB_OK больше говорит о типе окна, чем число 1, хотя по сути это одно и тоже).

И на последок о аргументах функции MessageBoxA. Первый аргумент - NULL, говорит о том, что окно сообщения не имеет родителя. Оператор ADDR используется, когда необходимо передать не значение переменной, а ее адрес. Последний аргумент - MB_OK, сообщает о том, что окно будет иметь иконку в виде восклицательного знака и кнопку OK.



Комментарии

отсутствуют

Добавление комментария


Ваше имя (на форуме):

Ваш пароль (на форуме):

Комментарии могут добавлять только пользователи,
зарегистрированные на форуме данного сайта. Если Вы не
зарегистрированы, то сначала зарегистрируйтесь тут

Комментарий:





Главная     Программы     Статьи     Разное     Форум     Контакты