Доброго время суток, уважаемые подписчики. Сегодня у нас первый урок ассемблера под Windows. А что есть Windows?! В переводе с английского это значит окна, и самым главным элементом Windows, на мой взгляд, являются окна.(Думаю MessageBox все уже умеют вызывать;) В этом уроке Вы узнаете как создавать оконное приложение на языке ассемблер. Для начала нам нужны инструменты для компиляции наших программ, поэтому я предполагаю, что следующие программы у Вас есть(всё это есть в MASM32):
- ml.exe
- link.exe
- kernel32.lib
- user32.lib
- mspdb50.dll
Для написания програм Вам понадобится любой текстовой редактор, я лично пользуюсь блокнотом (Notepad) из стандартной инсталяции Windows. На мой взгляд, лучше создать директорию, в которую сложить все эти файлы, и в которой создавать свои, но это личное дело каждого.
В Windows, в отличии от Доса, всё происходит путём обращения к системным функциям, а прирывания используются для системных нужд. Существует набор так называемых библиотек (файлы с расширением .dll), к которым и происходит обращение. Библиотеки удобны тем, что их можно загрузить в память, если они требуются, и выгрузить, когда их никто не использует. Также одну и ту же библиотеку может использовать одновременно несколько программ. То есть это, как процедуры в памяти, которые можно использовать из любого места памяти. Однако надо сказать программе, где находятся эти процедуры. Именно для этого нам и нужны файлы kernel32.lib и user32.lib, они и содержат эти метки. Но чтоб ассемблер мог понять что они значат, и как их использовать, нам самим нужно создать файлы .inc с описанием процедур. Поэтому для начала нам потребуется создать два файла, kernel32.inc и user32.inc. В них нам надо указать, какие процедуры из какой библиотеки нам доступны.
kernel32.inc:
includelib kernel32.lib
extrn __imp__GetModuleHandleA@4:dword
extrn __imp__ExitProcess@4:dword
ExitProcess equ __imp__ExitProcess@4
GetModuleHandle equ __imp__GetModuleHandleA@4
|
user32.inc:
includelib user32.lib
extrn __imp__DispatchMessageA@4:dword
extrn __imp__TranslateMessage@4:dword
extrn __imp__GetMessageA@16:dword
extrn __imp__LoadIconA@8:dword
extrn __imp__UpdateWindow@4:dword
extrn __imp__ShowWindow@8:dword
extrn __imp__CreateWindowExA@48:dword
extrn __imp__DefWindowProcA@16:dword
extrn __imp__PostQuitMessage@4:dword
extrn __imp__RegisterClassExA@4:dword
extrn __imp__LoadCursorA@8:dword
extrn __imp__DestroyWindow@4:dword
DispatchMessage equ __imp__DispatchMessageA@4
TranslateMessage equ __imp__TranslateMessage@4
GetMessage equ __imp__GetMessageA@16
LoadIcon equ __imp__LoadIconA@8
UpdateWindow equ __imp__UpdateWindow@4
ShowWindow equ __imp__ShowWindow@8
CreateWindowEx equ __imp__CreateWindowExA@48
DefWindowProc equ __imp__DefWindowProcA@16
PostQuitMessage equ __imp__PostQuitMessage@4
RegisterClassEx equ __imp__RegisterClassExA@4
LoadCursor equ __imp__LoadCursorA@8
DestroyWindow equ __imp__DestroyWindow@4
|
Ещё есть один момент. Нам понадобиться структуры и другие подобные описания. В принципе их можно спокойно записать и в сам файл программы, но зачем захламлять код. Я считаю достаточно удобным создать файл def32.inc и записать в него все параметры!
def32.inc:
IDI_APPLICATION equ 32512
WM_DESTROY equ 2
CS_HREDRAW equ 2
CS_VREDRAW equ 1
CW_USEDEFAULT equ 80000000h
WS_OVERLAPPEDWINDOW equ 0CF0000h
IDC_ARROW equ 32512
SW_SHOWNORMAL equ 1
COLOR_WINDOW equ 5
WNDCLASSEX struc
cbSize dd ?
style dd ?
lpfnWndProc dd ?
cbClsExtra dd ?
cbWndExtra dd ?
hInstance dd ?
hIcon dd ?
hCursor dd ?
hbrBackground dd ?
lpszMenuName dd ?
lpszClassName dd ?
hIconSm dd ?
WNDCLASSEX ends
MSG struc
hwnd dd ?
message dd ?
wParam dd ?
lParam dd ?
time dd ?
pt dq ?
MSG ends
|
Всё, приготовления закончены! Теперь начинаем писать программу!
window.asm:
;добавляем наши библиотеки и описания
include def32.inc
include user32.inc
include kernel32.inc
.386 ;модель памяти flat появилась на 386 - ом процессоре
.model flat
;константы
.const
class db "window class 1",0 ;класс окна
name_ db "Da window!",0 ;Имя окна
;переменные
.data
wc wndclassex<4*12, cs_hredraw or cs_vredraw, offset win_proc,0,0,?,?,?, color_window+1,0,offset class,0>
.data?
msg_ msg <?,?,?,?,?,?> ;сообщения
;сам код
.code
_start: ;начальная метка
xor ebx,ebx
push ebx
call GetModuleHandle
mov esi,eax ;получаем hanle нашей программы в esi
mov dword ptr wc.hInstance,eax ;так-же устанавливаем его отцом нашего окна
push IDI_APPLICATION
push ebx
call LoadIcon
mov wc.hIcon,eax ;стандартная иконка Windows
push idc_arrow
push ebx
call LoadCursor
mov wc.hCursor,eax ;стандартную мышь
push offset wc
call RegisterClassEx ;регистрируем его (переменную окна wc)
mov ecx,CW_USEDEFAULT
push ebx
push esi
push ebx
push ebx
push ecx
push ecx
push ecx
push ecx
push WS_OVERLAPPEDWINDOW
push offset name_
push offset class
push ebx
call CreateWindowEx ;И создаём окно!
push eax
push SW_SHOWNORMAL
push eax
call ShowWindow ;показываем его народу;)
call UpdateWindow ;показываем его и обновляем!
mov edi,offset msg_
main_:
push ebx
push ebx
push ebx
push edi
call GetMessage ;получаем сообщение
test eax,eax
jz exit_ ;если это 0, то выход
push edi
call TranslateMessage
push edi
call DispatchMessage ;преобразуем сообщения для процедуры окна.
jmp main_
exit_:
push ebx
call ExitProcess ;выход из программы
win_proc proc ;процедура окна!
push ebp
mov ebp,esp
wp_hWnd equ dword ptr [ebp+08h] ;так как сообщения передаются
wp_uMsg equ dword ptr [ebp+0Ch] ;при помощи стека,
wp_wParam equ dword ptr [ebp+10h] ;то можно напрямую
wp_lParam equ dword ptr [ebp+14h] ;к ним обращатся!
cmp wp_uMsg,WM_DESTROY ;если сообщение о закрытии окна
jne not_
push 0
call PostQuitMessage ;послать сообщение о выходе
jmp end_
not_: ;если нет
leave
jmp DefWindowProc ;Пусть Windows обрабатывает сообщение
end_:
leave
;Возвращение из процедуры с удалением из стека четырёх(16/4=4) параметров
ret 16
win_proc endp
end _start
|
Конечно это кажется каким-то бредом, однако в этом есть логика!
И, самое главное, как это компилировать (переводить в запускаемый формат!). Для этого Вам понадобятся вышеописанные инструменты! Можно компилировать двумя способами, в ручную и "батником" (файл формата .bat, в который вносятся все команды поочерёдно в порядке их выполнения!). Я предпочитаю батник, и Вам советую. Итак нужно создать файл имя.bat и вписать в него:
ml /c /coff имя_программы.asm
link имя_программы.obj /subsystem:windows
где имя_программы имя файла с кодом!
К сожалению, еслиб я ещё всё объяснил, то этот урок занял-бы конкретно времени и места, к тому же всегда есть те, кто жаждет понять сам, без чьей либо помощи, поэтому здесь только очень поверхносная информация, обещаю в течении пары дней описать всё это дело подробно, а на пока хватит! Если что пишите, Dark_Lord