Перед нами структура PE(PortableExecutable)файла Win (.EXE) и Common Object File Format (COFF). Далее идет описание секций и их атрибутов в порядке Section Name Content Characteristics.
Бывают еще секции .debug и .drectve но их, как правило, в исполняемом файле нет, поскольку они содержат информацию для линкера и отладчика соответственно.
Меню
Windows во многом упрощает нам работу программ, он берёт на себя практически все заботы об обслуживанию нашего окна, предлагает нам диалоги типа MessageBox... Ещё одна очень полезная вещь, это так называемые ресурсы. Нам достаточно записать лишь параметры нужных нам объектов в файл ресурсов, а Windows берёт на себя задачу создания соответствующих объектов и их обработки. Один из объектов ресурсов, он же наиболее часто используемый, меню. Все ресурсы наиболее удобно писать в редакторе ресурсов, например в Borland Workshop, (Распаковывется при помощи WinRar3) однако структура меню настолько легка, что её легче сделать вручную! Для этого надо создать файл расширения .rc , давайте создадим menu.rc, и записать в него следующие:
Прежде чем идти дальше, давайте разберёмся, что же мы записали. Заранее хочу предупредить, что файлы ресурсов пишутся не на ассемблере, именно поэтому я и советую работать с редактором ресурсов. Итак, первые четыре строчки равны следующим строкам на ассемблере:
то есть мы создаём условные значения, которые при компиляции заменяются их реальными значениями. Следующйё строкой мы объявляем меню с именем IDM_MENU, объявляем одну подменю, в которой находится три пункта и разделительная полоса. и ещё одну кнопку в меню. А теперь давайте добавим информацию о меню в window.asm:
include def32.inc include user32.inc include kernel32.inc .386 .model flat .const class db "window class 1",0 name_ db "Da window!",0 sure db "Предупреждение",0 ask db "Вы уверены, что хотите выйти?",0 menu_name db 'IDM_MENU',0 save_msg db 'Вы выбрали пункт Сохранить',0 open_msg db 'Вы выбрали пункт Загрузить',0 test_msg db 'Вы выбрали пункт Тест',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 mov dword ptr wc.hInstance,eax push IDI_APPLICATION push ebx call LoadIcon mov wc.hIcon,eax push idc_arrow push ebx call LoadCursor mov wc.hCursor,eax push offset wc call RegisterClassEx push offset menu_name push esi call LoadMenu mov ecx,CW_USEDEFAULT push ebx push esi push eax ;Это не новая строка 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_ 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_CLOSE jne not_close push MB_YESNO push offset sure push offset ask push 0 call MessageBox cmp eax,IDYES je not_close mov wp_uMsg,0 jmp not_ not_close: cmp wp_uMsg,WM_DESTROY jne not_ push 0 call PostQuitMessage jmp end_ not_: cmp wp_uMsg,WM_COMMAND jne not_all mov eax,wp_wParam jmp dword ptr menus[eax*4] menus dd offset menu_test dd offset menu_open dd offset menu_save dd offset menu_exit menu_test: mov eax,offset test_msg jmp message_ menu_open: mov eax,offset open_msg jmp message_ menu_save: mov eax,offset save_msg message_: push MB_OK push offset menu_name push eax push wp_hWnd call MessageBox jmp end_ menu_exit: push wp_hWnd call DestroyWindow end_: leave ret 16 not_all: leave jmp DefWindowProc win_proc endp end _start
А теперь давайте разберёмся в новых строках. Итак, первые 4 новые строки, это создание виртуальных значений, это я думаю понятно. Дальше мы создаём 4 переменные, одну с именем меню, и три с сообщениями для messagebox. Следующие добавление, это загрузка меню из ресурсов, выполняемая процедурой LoadMenu, которая получает два параметра, имя меню и handle процесса. Далее мы заменяем одну строку при создании окна. Прошу обратить внимание, что эта строка уже существовала в прошлых примерах, просто мы помещали в стек не handle меню, а 0! Единственное, что нам осталось сделать, это добавить в процедуру нашего окна обработку событий меню. При получении сообщения от меню, главное сообщение содержит команду WM_COMMAND, а уже первый параметр сообщения содержит номер выбранного меню. То есть нам надо добавить только обработку сообщения wm_command. И только если сообщение действительно WM_COMMAND, обрабатывать первый параметр. При этом в файл user32.inc следует дописать следующие строки: