Меню сайта

Урок 1. ASSEMBLER & WIN32 ( 1 Часть )

Программирование на ассемблере под Win32 воспринимается весьма
не однозначно. Считается, что написание приложений слишком сложно
для применения ассемблера. Собственно обсуждению того насколько
оправдана такая точка зрения и посвящена данная статья. Она не ставит
своей целью обучение программированию под Win32 или обучение
ассемблеру, я подразумеваю, что читатели имеют определённые знания
в этих областях.

В отличие от программирования под DOS, где программы написанные
на языках высокого уровня (ЯВУ) были мало похожи на свои аналоги,
написанные на ассемблере, приложения под Win32 имеют гораздо
больше общего. В первую очередь, это связано с тем, что обращение к
сервису операционной системы в Windows осуществляется
посредством вызова функций, а не прерываний, что было характерно
для DOS. Здесь нет передачи параметров в регистрах при обращении к
сервисным функциям и, соответственно, нет и множества
результирующих значений возвращаемых в регистрах общего
назначения и регистре флагов. Следовательно проще запомнить и
использовать протоколы вызова функций системного сервиса. С другой
стороны, в Win32 нельзя непосредственно работать с аппаратным
уровнем, чем «грешили” программы для DOS. Вообще написание
программ под Win32 стало значительно проще и это обусловлено
следующими факторами:
отсутствие startup кода, характерного для приложений и
динамических библиотек написанных под Windows 3.x-
гибкая система адресации к памяти: возможность обращаться к
памяти через любой регистр общего назначения- «отсутствие”
сегментных регистров-
доступность больших объёмов виртуальной памяти-
развитый сервис операционной системы, обилие функций,
облегчающих разработку приложений-
многообразие и доступность средств создания интерфейса с
пользователем (диалоги, меню и т.п.).

Современный ассемблер, к которому относится и TASM 5.0 фирмы
Borland International Inc., в свою очередь, развивал средства, которые
ранее были характерны только для ЯВУ. К таким средствам можно
отнести макроопределение вызова процедур, возможность введения
шаблонов процедур (описание прототипов) и даже
объектно-ориентированные расширения. Однако, ассемблер сохранил и
такой прекрасный инструмент, как макроопределения вводимые
пользователем, полноценного аналога которому нет ни в одном ЯВУ.

Все эти факторы позволяют рассматривать ассемблер, как
самостоятельный инструмент для написания приложений под
платформы Win32 (Windows NT и Windows 95). Как иллюстрацию
данного положения, рассмотрим простой пример приложения,
работающего с диалоговым окном. Пример 1. Программа
работы с диалогом Файл, содержащий текст приложения, dlg.asm

IDEAL
P586
RADIX — — 16
MODEL — — FLAT
%NOINCL
%NOLIST
include «winconst.inc» — — — — — — — — — — API Win32 consts
include «winptype.inc» — — — — — — — — — — API Win32 functions prototype
include «winprocs.inc» — — — — — — — — — — API Win32 function
include «resource.inc» — — — — — — — — — — resource consts
MAX_USER_NAME — — = — — — — — — 20
DataSeg
szAppName — — — — — — db — — — — — ‘Demo 1’, 0
szHello — — — — — — — — db — — — — — ‘Hello, ‘
szUser — — — — — — — — — db — — — — — MAX_USER_NAME dup (0)
CodeSeg
Start: — — — — — — — — — call — — — GetModuleHandleA, — — — — — — 0
— — — — — — — — — — — — — — — call — — — DialogBoxParamA, — — — — — — — eax, IDD_DIALOG, 0, offset DlgProc, 0
— — — — — — — — — — — — — — — cmp — — — — eax,IDOK
— — — — — — — — — — — — — — — jne — — — — bye
— — — — — — — — — — — — — — — call — — — MessageBoxA, — — — — — — — — — — — 0, offset szHello, — — — — — &#92-
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — offset szAppName, — — — — — — &#92-
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — MB_OK or MB_ICONINFORMATION
bye: — — — — — — — — — — — call — — — ExitProcess, — — — — — — — — — — — 0
public — stdcall DlgProc
proc — — — DlgProc stdcall
arg — — — — @@hDlg — :dword, @@iMsg — :dword, @@wPar — :dword, @@lPar — :dword
— — — — — — — — — — — — — — — mov — — — — eax,[@@iMsg]
— — — — — — — — — — — — — — — cmp — — — — eax,WM_INITDIALOG
— — — — — — — — — — — — — — — je — — — — — @@init
— — — — — — —
— — — — — — — — cmp — — — — eax,WM_COMMAND
— — — — — — — — — — — — — — — jne — — — — @@ret_false
— — — — — — — — — — — — — — — mov — — — — eax,[@@wPar]
— — — — — — — — — — — — — — — cmp — — — — eax,IDCANCEL
— — — — — — — — — — — — — — — je — — — — — @@cancel
— — — — — — — — — — — — — — — cmp — — — — eax,IDOK
— — — — — — — — — — — — — — — jne — — — — @@ret_false
— — — — — — — — — — — — — — — call — — — GetDlgItemTextA, — — — — — — — [@@hDlg[, IDR_NAME, — — — — &#92-
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — offset szUser, MAX_USER_NAME
— — — — — — — — — — — — — — — mov — — — — eax,IDOK
@@cancel: — — — — — — call — — — EndDialog, — — — — — — — — — — — — — [@@hDlg[, eax
@@ret_false: — — — xor — — — — eax,eax
— — — — — — — — — — — — — — — ret
@@init: — — — — — — — — call — — — GetDlgItem, — — — — — — — — — — — — [@@hDlg], IDR_NAME
— — — — — — — — — — — — — — — call — — — SetFocus, — — — — — — — — — — — — — — eax
— — — — — — — — — — — — — — — jmp — — — — @@ret_false
endp — — — DlgProc
end — — — — Start

— Файл ресурсов dlg.rc —

#include «resource.h»
IDD_DIALOG DIALOGEX 0, 0, 187, 95
STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_CLIENTEDGE
CAPTION «Dialog»
FONT 8, «MS Sans Serif»
BEGIN
— — — DEFPUSHBUTTON — — «OK»,IDOK,134,76,50,14
— — — PUSHBUTTON — — — — — «Cancel»,IDCANCEL,73,76,50,14
— — — LTEXT — — — — — — — — — — «Type your name»,IDC_STATIC,4,36,52,8
— — — EDITTEXT — — — — — — — IDR_NAME,72,32,112,14,ES_AUTOHSCROLL
END

Остальные файлы из данного примера, приведены в приложении 1.

Сразу после метки Start, программа обращается к функции API Win32
GetModuleHandle для получения handle данного модуля (данный
параметр чаще именуют как handle of instance). Получив handle, мы
вызываем диалог, созданный либо вручную, либо с помощью
какой-либо программы построителя ресурсов. Далее программа
проверяет результат работы диалогового окна. Если пользователь вышел
из диалога посредством нажатия клавиши OK, то приложение запускает
MessageBox с текстом приветствия.

Диалоговая процедура обрабатывает следующие сообщения. При
инициализации диалога (WM_INITDIALOG) она просит Windows
установить фокус на поле ввода имени пользователя. Сообщение
WM_COMMAND обрабатывается в таком порядке: делается проверка
на код нажатия клавиши. Если была нажата клавиша OK, то
пользовательский ввод копируется в переменную szValue, если же была
нажата клавиша Cancel, то копирования не производится. Но и в том и
другом случае вызывается функция

окончания диалога: EndDialog. Остальные сообщения в группе
WM_COMMAND просто игнорируются, предоставляя Windows
действовать по умолчанию.

Вы можете сравнить приведённую программу с аналогичной
программой, написанной на ЯВУ, разница в написании будет
незначительна. Очевидно те, кто писал приложения на ассемблере под
Windows 3.x, отметят тот факт, что исчезла необходимость в сложном и
громоздком startup коде. Теперь приложение выглядит более просто и
естественно.

Пример 2. Динамическая библиотека

Написание динамических библиотек под Win32 также значительно
упростилось, по сравнению с тем, как это делалось под Windows 3.x.
Исчезла необходимость вставлять startup код, а использование четырёх
событий инициализации/деинициализации на уровне процессов и
потоков, кажется логичным.

Рассмотрим простой пример динамической библиотеки, в которой
всего одна функция, преобразования целого числа в строку в
шестнадцатеричной системе счисления. Файл mylib.asm —

Ideal
P586
Radix — — 16
Model — — flat
DLL_PROCESS_ATTACH — — — — — = 1
extrn — — GetVersion: — — — — proc
DataSeg
hInst — — — — — — — — — — dd — — — — — 0
OSVer — — — — — — — — — — dw — — — — — 0
CodeSeg
proc — — — libEntry — — — — — — — stdcall
arg — — — — @@hInst :dword, @@rsn — — :dword, @@rsrv — :dword
— — — — — — — — — — — — — — — cmp — — — — [@@rsn],DLL_PROCESS_ATTACH
— — — — — — — — — — — — — — — jne — — — — @@1
— — — — — — — — — — — — — — — call — — — GetVersion
— — — — — — — — — — — — — — — mov — — — — [OSVer],ax
— — — — — — — — — — — — — — — mov — — — — eax,[@@hInst]
— — — — — — — — — — — — — — — mov — — -&nb
sp- [hInst],eax
@@1: — — — — — — — — — — — mov — — — — eax,1
— — — — — — — — — — — — — — — ret
endP — — — libEntry
public — stdcall Hex2Str
proc — — — Hex2Str stdcall
arg — — — — @@num — — :dword, @@str — — :dword
uses — — — ebx
— — — — — — — — — — — — — — — mov — — — — eax,[@@num]
— — — — — — — — — — — — — — — mov — — — — ebx,[@@str]
— — — — — — — — — — — — — — — mov — — — — ecx,7
@@1: — — — — — — — — — — — mov — — — — edx,eax
— — — — — — — — — — — — — — — shr — — — — eax,4
— — — — — — — — — — — — — — — and — — — — edx,0F
— — — — — — — — — — — — — — — cmp — — — — edx,0A
— — — — — — — — — — — — — — — jae — — — — @@2
— — — — — — — — — — — — — — — add — — — — edx,’0′
— — — — — — — — — — — — — — — jmp — — — — @@3
@@2: — — — — — — — — — — — add — — — — edx,’A’ — 0A
@@3: — — — — — — — — — — — mov — — — — [byte ebx + ecx],dl
— — — — — — — — — — — — — — — dec — — — — ecx
— — — — — — — — — — — — — — — jns — — — — @@1
— — — — — — — — — — — — — — — mov — — — — [byte ebx + 8],0
— — — — — — — — — — — — — — — ret
endp — — — Hex2Str
end — — — — libEntry

-Остальные файлы, которые необходимы для данного примера, можно
найти в приложении 2.

Краткие комментарии к динамической библиотеке

Процедура libEntry является точкой входа в динамическую библиотеку,
её не надо объявлять как экспортируемую, загрузчик сам определяет её
местонахождение. LibEntry может вызываться в четырёх случаях:
при проецировании библиотеки в адресное пространство
процесса (DLL_PROCESS_ATTACH)-
при первом вызове библиотеки из потока
(DLL_THREAD_ATTACH), например, с помощью функции
LoadLibrary-
при выгрузке библиотеки потоком (DLL_THREAD_DETACH)-
при выгрузке библиотеки из адресного пространства процесса
(DLL_PROCESS_DETACH).

В нашем примере обрабатывается только первое из событий
DLL_PROCESS_ATTACH. При обработке данного события библиотека
запрашивает версию OS сохраняет её, а также свой handle of instance.

Библиотека содержит только одну экспортируемую функцию, которая
собственно не требует пояснений. Вы, пожалуй, можете обратить
внимание на то, как производится запись преобразованных значений.
Интересна система адресации посредством двух регистров общего
назначения: ebx + ecx, она позволяет нам использовать регистр ecx
одновременно и как счётчик и как составную часть адреса.

Пример 3. Оконное приложение

Файл dmenu.asm —

Ideal
P586
Radix — — 16
Model — — flat
struc — — WndClassEx
— — — — — — — cbSize — — — — — — — — — dd — — — — — 0
— — — — — — — style — — — — — — — — — — dd — — — — — 0
— — — — — — — lpfnWndProc — — — — dd — — — — — 0
— — — — — — — cbClsExtra — — — — — dd — — — — — 0
— — — — — — — cbWndExtra — — — — — dd — — — — — 0
— — — — — — — hInstance — — — — — — dd — — — — — 0
— — — — — — — hIcon — — — — — — — — — — dd — — — — — 0
— — — — — — — hCursor — — — — — — — — dd — — — — — 0
— — — — — — — hbrBackground — — dd — — — — — 0
— — — — — — — lpszMenuName — — — dd — — — — — 0
— — — — — — — lpszClassName — — dd — — — — — 0
— — — — — — — hIconSm — — — — — — — — dd — — — — — 0
ends — — — WndClassEx
struc — — Point
— — — — — — — x — — — — — — — — — — — — — — dd — — — — — 0
— — — — — — — y — — — — — — — — — — — — — — dd — — — — — 0
ends — — — Point
struc — — msgStruc
— — — — — — — hwnd — — — — — — — — — — — dd — — — — — 0
— — — — — — — message — — — — — — — — dd — — — — — 0
— — — — — — — wParam — — — — — — — — — dd — — — — — 0
— — — — — — — lParam — — — — — — — — — dd — — — — — 0
— — — — — — — time — — — — — — — — — — — dd — — — — — 0
— — — — — — — pnt — — — — — — — — — — — — Point — — &lt-&gt-
ends — — — msgStruc
MyMenu — — — — — — — — — — — — — — — — — = 0065
ID_OPEN — — — — — — — — — — — — — — — — = 9C41
ID_SAVE — — — — — — — — — — — — — — — — = 9
C42
ID_EXIT — — — — — — — — — — — — — — — — = 9C43
CS_HREDRAW — — — — — — — — — — — — — = 0001
CS_VREDRAW — — — — — — — — — — — — — = 0002
IDI_APPLICATION — — — — — — — — = 7F00
IDC_ARROW — — — — — — — — — — — — — — = 00007F00
COLOR_WINDOW — — — — — — — — — — — = 5
WS_EX_WINDOWEDGE — — — — — — — = 00000100
WS_EX_CLIENTEDGE — — — — — — — = 00000200
WS_EX_OVERLAPPEDWINDOW — = WS_EX_WINDOWEDGE OR WS_EX_CLIENTEDGE
WS_OVERLAPPED — — — — — — — — — — = 00000000
WS_CAPTION — — — — — — — — — — — — — = 00C00000
WS_SYSMENU — — — — — — — — — — — — — = 00080000
WS_THICKFRAME — — — — — — — — — — = 00040000
WS_MINIMIZEBOX — — — — — — — — — = 00020000
WS_MAXIMIZEBOX — — — — — — — — — = 00010000
WS_OVERLAPPEDWINDOW — — — — = WS_OVERLAPPED — — — — — — — — OR — — — — — WS_CAPTION — — — — — — — OR &#92-
— — — — — — — — — — — — — — — — — — — — — — — — — WS_SYSMENU — — — — — — — — — — — OR — — — — — WS_THICKFRAME — — — — OR &#92-
— — — — — — — — — — — — — — — — — — — — — — — — — WS_MINIMIZEBOX — — — — — — — OR — — — — — WS_MAXIMIZEBOX —
CW_USEDEFAULT — — — — — — — — — — = 80000000
SW_SHOW — — — — — — — — — — — — — — — — = 5
WM_COMMAND — — — — — — — — — — — — — = 0111
WM_DESTROY — — — — — — — — — — — — — = 0002
WM_CLOSE — — — — — — — — — — — — — — — = 0010
MB_OK — — — — — — — — — — — — — — — — — — = 0
PROCTYPE — — — — — — — ptGetModuleHandle — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpModuleName — — — :dword
PROCTYPE — — — — — — — ptLoadIcon — — — — — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — hInstance — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpIconName — — — — — :dword
PROCTYPE — — — — — — — ptLoadCursor — — — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — hInstance — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpCursorName — — — :dword
PROCTYPE — — — — — — — ptLoadMenu — — — — — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — hInstance — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpMenuName — — — — — :dword
PROCTYPE — — — — — — — ptRegisterClassEx — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpwcx — — — — — — — — — — :dword
PROCTYPE — — — — — — — ptCreateWindowEx — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — dwExStyle — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpClassName — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpWindowName — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — dwStyle — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — x — — — — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — y — — — — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — nWidth — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — nHeight — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — hWndParent — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — hMenu — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — hInstance — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpParam — — — — — — — — :dword
PROCTYPE — — — — — — — ptShowWindow — — — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — hWnd — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — —
— — nCmdShow — — — — — — — :dword
PROCTYPE — — — — — — — ptUpdateWindow — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — hWnd — — — — — — — — — — — :dword
PROCTYPE — — — — — — — ptGetMessage — — — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — pMsg — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — hWnd — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — wMsgFilterMin — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — wMsgFilterMax — — :dword
PROCTYPE — — — — — — — ptTranslateMessage — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpMsg — — — — — — — — — — :dword
PROCTYPE — — — — — — — ptDispatchMessage — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — pmsg — — — — — — — — — — — :dword
PROCTYPE — — — — — — — ptSetMenu — — — — — — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — hWnd — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — hMenu — — — — — — — — — — :dword
PROCTYPE — — — — — — — ptPostQuitMessage — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — nExitCode — — — — — — :dword
PROCTYPE — — — — — — — ptDefWindowProc — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — hWnd — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — Msg — — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — wParam — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lParam — — — — — — — — — :dword
PROCTYPE — — — — — — — ptSendMessage — — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — hWnd — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — Msg — — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — wParam — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lParam — — — — — — — — — :dword
PROCTYPE — — — — — — — ptMessageBox — — — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — hWnd — — — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpText — — — — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — lpCaption — — — — — — :dword, &#92-
— — — — — — — — — — — — — — — — — — — — — — — uType — — — — — — — — — — :dword
PROCTYPE — — — — — — — ptExitProcess — — — — — — — — — — stdcall &#92-
— — — — — — — — — — — — — — — — — — — — — — — exitCode — — — — — — — :dword
extrn — — — — — — — — — — GetModuleHandleA — — — — — — — :ptGetModuleHandle
extrn — — — — — — — — — — LoadIconA — — — — — — — — — — — — — — :ptLoadIcon
extrn — — — — — — — — — — LoadCursorA — — — — — — — — — — — — :ptLoadCursor
extrn — — — — — — — — — — RegisterClassExA — — — — — — — :ptRegisterClassEx
extrn — — — — — — — — — — LoadMenuA — — — — — — — — — — — — — — :ptLoadMenu
extrn — — — — — — — — — — CreateWindowExA — — — — — — — — :ptCreateWindowEx
extrn — — — — — — — — — — ShowWindow — — — — — — — — — — — — — :ptShowWindow
extrn — — — — — — — — — — UpdateWindow — — — — — — — — — — — :ptUpdateWindow
extrn — — — — — — — — — — GetMessageA — — — — — — — — — — — — :ptGetMessage
extrn — — — — — — — — — — TranslateMessage — — — — — — — :ptTranslateMessage
extrn — — — — — — — — — — DispatchMessageA — — — — — — — :ptDispatchMessage
extrn — — — — — — — -&nb
sp- — SetMenu — — — — — — — — — — — — — — — — :ptSetMenu
extrn — — — — — — — — — — PostQuitMessage — — — — — — — — :ptPostQuitMessage
extrn — — — — — — — — — — DefWindowProcA — — — — — — — — — :ptDefWindowProc
extrn — — — — — — — — — — SendMessageA — — — — — — — — — — — :ptSendMessage
extrn — — — — — — — — — — MessageBoxA — — — — — — — — — — — — :ptMessageBox
extrn — — — — — — — — — — ExitProcess — — — — — — — — — — — — :ptExitProcess
UDataSeg
hInst — — — — — — — — — — dd — — — — — — — — — — — — — ?
hWnd — — — — — — — — — — — dd — — — — — — — — — — — — — ?
IFNDEF — VER1
hMenu — — — — — — — — — — dd — — — — — — — — — — — — — ?
ENDIF
DataSeg
msg — — — — — — — — — — — — msgStruc — — — — — — — &lt-&gt-
classTitle — — — — — db — — — — — ‘Menu demo’, 0
wndTitle — — — — — — — db — — — — — ‘Demo program’, 0
msg_open_txt — — — db — — — — — ‘You selected open’, 0
msg_open_tlt — — — db — — — — — ‘Open box’, 0
msg_save_txt — — — db — — — — — ‘You selected save’, 0
msg_save_tlt — — — db — — — — — ‘Save box’, 0
CodeSeg
Start: — call — — — GetModuleHandleA, — — — — — — 0 — — — — — — — — — — — — — — — получаем hInstance
— — — — — — — mov — — — — [hInst],eax
— — — — — — — sub — — — — esp,SIZE WndClassEx — — — — — — — — — — — — — — — — — — — — — выделяем место в стеке
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — заполняем структуру WndClassEx
— — — — — — — mov — — — — [(WndClassEx esp).cbSize],SIZE WndClassEx
— — — — — — — mov — — — — [(WndClassEx esp).style],CS_HREDRAW or CS_VREDRAW
— — — — — — — mov — — — — [(WndClassEx esp).lpfnWndProc],offset WndProc
— — — — — — — mov — — — — [(WndClassEx esp).cbWndExtra],0
— — — — — — — mov — — — — [(WndClassEx esp).cbClsExtra],0
— — — — — — — mov — — — — [(WndClassEx esp).hInstance],eax
— — — — — — — call — — — LoadIconA, — — — — — — — — — — — — — 0, IDI_APPLICATION
— — — — — — — mov — — — — [(WndClassEx esp).hIcon],eax
— — — — — — — call — — — LoadCursorA, — — — — — — — — — — — 0, IDC_ARROW
— — — — — — — mov — — — — [(WndClassEx esp).hCursor],eax
— — — — — — — mov — — — — [(WndClassEx esp).hbrBackground],COLOR_WINDOW
IFDEF — — VER1
— — — — — — — mov — — — — [(WndClassEx esp).lpszMenuName],MyMenu
ELSE
— — — — — — — mov — — — — [(WndClassEx esp).lpszMenuName],0
ENDIF
— — — — — — — mov — — — — [(WndClassEx esp).lpszClassName],offset classTitle
— — — — — — — mov — — — — [(WndClassEx esp).hIconSm],0
— — — — — — — call — — — RegisterClassExA, — — — — — — esp — — — — — — — — — — — — — регистрируем окно
— — — — — — — add — — — — esp,SIZE WndClassEx — — — — — — — — — — — — — — — — — — — — — восстановим стек
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — создадим окно
IFNDEF — VER2
— — — — — — — call — — — CreateWindowExA, — — — — — — — WS_EX_OVERLAPPEDWINDOW, &#92- extended window style
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — offset classTitle, — — — — — &#92- pointer to registered class name —
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — offset wndTitle, — — — — — — — &#92- pointer to window name
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — WS_OVERLAPPEDWINDOW, — — — &#92- window style
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — CW_USEDEFAULT, — — — — — — — — — &#92- horizontal position of window
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — CW_USEDEFAULT, — — — — — — — — — &#92- vertical position of window
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — CW_USEDEFAULT, — — — — — — — — — &#92- window width
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — CW_USEDEFAULT, — — -&nbs
p- — — — — — &#92- window height
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 0, — — — — — — — — — — — — — — — — — — — — — &#92- handle to parent or owner window
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 0, — — — — — — — — — — — — — — — — — — — — — &#92- handle to menu, or child-window identifier
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — [hInst], — — — — — — — — — — — — — — — &#92- handle to application instance
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 0 — — — — — — — — — — — — — — — — — — — — — — — pointer to window-creation data
ELSE
— — — — — — — call — — — LoadMenu, — — — — — — — — — — — — — — hInst, MyMenu
— — — — — — — mov — — — — [hMenu],eax
— — — — — — — call — — — CreateWindowExA, — — — — — — — WS_EX_OVERLAPPEDWINDOW, &#92- extended window style
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — offset classTitle, — — — — — &#92- pointer to registered class name —
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — offset wndTitle, — — — — — — — &#92- pointer to window name
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — WS_OVERLAPPEDWINDOW, — — — &#92- window style
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — CW_USEDEFAULT, — — — — — — — — — &#92- horizontal position of window
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — CW_USEDEFAULT, — — — — — — — — — &#92- vertical position of window
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — CW_USEDEFAULT, — — — — — — — — — &#92- window width
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — CW_USEDEFAULT, — — — — — — — — — &#92- window height
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 0, — — — — — — — — — — — — — — — — — — — — — &#92- handle to parent or owner window
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — eax, — — — — — — — — — — — — — — — — — — — &#92- handle to menu, or child-window identifier
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — [hInst], — — — — — — — — — — — — — — — &#92- handle to application instance
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 0 — — — — — — — — — — — — — — — — — — — — — — — pointer to window-creation data
ENDIF
— — — — — — — mov — — — — [hWnd],eax
— — — — — — — call — — — ShowWindow, — — — — — — — — — — — — eax, SW_SHOW — — — — — — — — — — — — show window
— — — — — — — call — — — UpdateWindow, — — — — — — — — — — [hWnd] — — — — — — — — — — — — — — — — — — redraw window
IFDEF — — VER3
— — — — — — — call — — — LoadMenuA, — — — — — — — — — — — — — [hInst], MyMenu
— — — — — — — mov — — — — [hMenu],eax
— — — — — — — call — — — SetMenu, — — — — — — — — — — — — — — — [hWnd], eax
ENDIF
msg_loop:
— — — — — — — call — — — GetMessageA, — — — — — — — — — — — offset msg, 0, 0, 0
— — — — — — — or — — — — — ax,ax
— — — — — — — jz — — — — — exit
— — — — — — — call — — — TranslateMessage, — — — — — — offset msg
— — — — — — — call — — — DispatchMessageA, — — — — — — offset msg
— — — — — — — jmp — — — — msg_loop
exit: — — call — — — ExitProcess, — — — — — — — — — — — 0
public — stdcall WndProc
proc — — — WndProc stdcall
arg — — — — @@hwnd: dword, — @@msg: — dword, — @@wPar: dword, — @@lPar: dword
— — — — — — — mov — — — — eax,[@@msg]
— —
— — — — — cmp — — — — eax,WM_COMMAND
— — — — — — — je — — — — — @@command
— — — — — — — cmp — — — — eax,WM_DESTROY
— — — — — — — jne — — — — @@default
— — — — — — — call — — — PostQuitMessage, — — — — — — — 0
— — — — — — — xor — — — — eax,eax
— — — — — — — jmp — — — — @@ret
@@default:
— — — — — — — call — — — DefWindowProcA, — — — — — — — — [@@hwnd], [@@msg], [@@wPar], [@@lPar]
@@ret: — ret
@@command:
— — — — — — — mov — — — — eax,[@@wPar]
— — — — — — — cmp — — — — eax,ID_OPEN
— — — — — — — je — — — — — @@open
— — — — — — — cmp — — — — eax,ID_SAVE
— — — — — — — je — — — — — @@save
— — — — — — — call — — — SendMessageA, — — — — — — — — — — [@@hwnd], WM_CLOSE, 0, 0
— — — — — — — xor — — — — eax,eax
— — — — — — — jmp — — — — @@ret
@@open: mov — — — — eax, offset msg_open_txt
— — — — — — — mov — — — — edx, offset msg_open_tlt
— — — — — — — jmp — — — — @@mess
@@save: mov — — — — eax, offset msg_save_txt
— — — — — — — mov — — — — edx, offset msg_save_tlt
@@mess: call — — — MessageBoxA, — — — — — — — — — — — 0, eax, edx, MB_OK
— — — — — — — xor — — — — eax,eax
— — — — — — — jmp — — — — @@ret
endp — — — WndProc
end — — — — Start


Меню раздела
Блок