 |
Ассемблер в примерах - Прошу прокомментировать строки программы
- Вопрос:
- Прошу прокомментировать строки программы
- Ответ:
-
;editor.asm
.386 ;работаем с 32-битными регистрами, и, вообще, создаем программу под Windows
.model flat,stdcall ;необходимая модел памяти под Windows
option casemap:none ;чтобы различать большие и малые буковки
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD ;прототип используемой функции
;подключим необходимые файлы
include /masm32/include/windows.inc
include /masm32/include/user32.inc
include /masm32/include/kernel32.inc
include /masm32/include/comdlg32.inc
includelib /masm32/lib/user32.lib
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/comdlg32.lib
;константы
.const
IDM_OPEN equ 1 ;пункт меню "open"
IDM_SAVE equ 2 ;пункт меню "save"
IDM_EXIT equ 3 ;пункт меню "exit"
MAXSIZE equ 260 ;размер буфера имени файла
MEMSIZE equ 65535 ;размер буфера в памяти для чтения файла
EditID equ 1 ;идентификатор органа управления "edit"
.data ;сегмент инициированных данных
ClassName db "Win32ASMEditClass",0 ;имя класса окна
AppName db "Win32 ASM Edit",0 ;имя приложения
EditClass db "edit",0 ;имя класса создаваемого органа управления
MenuName db "FirstMenu",0 ;имя меню из файла ресурсов
;Данные, необходимые для вызова стандартного диалога открытия файла
ofn OPENFILENAME <> ;основная структура
FilterString db "All Files",0,"*.*",0
db "Text Files",0,"*.txt", 0,0 ;набор фильтров
buffer db MAXSIZE dup(0) ;буфер для приема имени файла
.data? ;сегмент неинициированных данных
hInstance HINSTANCE ? ;handle экземпляра программы
CommandLine LPSTR ? ;адрес командной строки
hwndEdit HWND ? ;handle редактора
hFile HANDLE ? ;handle файла
hMemory HANDLE ? ;handle блока памяти
pMemory DWORD ? ;указатель на блок памяти
SizeReadWrite DWORD ? ;размер буфера для операций чтения/записи
.code ;сегмент кода
start: ;точка входа
invoke GetModuleHandle, NULL ;получим handle экземпляра программы
mov hInstance, eax
invoke GetCommandLine ;получим адрес командной строки
invoke WinMain, hInstance ,NULL, CommandLine, SW_SHOWDEFAULT ;вызов основной программы (в стандарте Windows)
invoke ExitProcess,eax ;выход из программы с кодом в EAX
WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
;локальные переменные
LOCAL wc:WNDCLASSEX ;структура для регистрации класса окна
LOCAL msg:MSG ;структура для обработки сообщений
LOCAL hwnd:HWND ;переменная для хранения handle окна
;заполним структуру wc
mov wc.cbSize,SIZEOF WNDCLASSEX ;размер структуры
mov wc.style, CS_HREDRAW or CS_VREDRAW ;стили класса
mov wc.lpfnWndProc, OFFSET WndProc ;функция окна
mov wc.cbClsExtra, NULL ;дополнительные данные класса окна
mov wc.cbWndExtra, NULL ; и для экземпляра окна нам не нужны
push hInst
pop wc.hInstance ;handle экземпляра программы
mov wc.hbrBackground, COLOR_WINDOW+1 ;фон
mov wc.lpszMenuName, OFFSET MenuName ;имя меню
mov wc.lpszClassName, OFFSET ClassName ;имя класса
invoke LoadIcon, NULL, IDI_APPLICATION ;стандартная иконка приложения
mov wc.hIcon, eax ; будет иконкой нашего приложения (32х32)
mov wc.hIconSm, eax ;16х16 тоже
invoke LoadCursor, NULL, IDC_ARROW ;указатель мыши на окне - стандартная стрелка
mov wc.hCursor, eax
invoke RegisterClassEx, addr wc ;регистрируем класс окна
;создаем основное окно
INVOKE CreateWindowEx, WS_EX_CLIENTEDGE, ADDR ClassName, ADDR AppName,\\\\\\\\
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,\\\\\\\\
CW_USEDEFAULT, 300, 200, NULL, NULL, \\\\\\\\
hInst, NULL
mov hwnd, eax ;сохраним handle окна
INVOKE ShowWindow, hwnd, SW_SHOWNORMAL ;покажем окно
INVOKE UpdateWindow, hwnd ;перерисуем
;цикл обработки сообщений
.WHILE TRUE ;бесконечный цикл
INVOKE GetMessage, ADDR msg, NULL, 0, 0 ;получаем сообщение из системной очереди
.BREAK .IF (!eax) ;если EAX = 0, то выход (после invoke PostQuitMessage, NULL)
INVOKE TranslateMessage, ADDR msg ;трансляция сообщений виртуальных клавиш в сообщения символов
INVOKE DispatchMessage, ADDR msg ;вызов функции окна для отработки сообщений
.ENDW
mov eax,msg.wParam ;код возврата
ret
WinMain endp
;функция окна
WndProc proc uses ebx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
;анализируем сообщения
.IF uMsg==WM_CREATE ;приходит во время создания окна
;создаем дочерний орган управления "edit"
INVOKE CreateWindowEx, NULL, ADDR EditClass, NULL,\\\\\\\\
WS_VISIBLE or WS_CHILD or ES_LEFT or ES_MULTILINE or\\\\\\\\
ES_AUTOHSCROLL or ES_AUTOVSCROLL, 0,\\\\\\\\
0, 0, 0, hWnd, EditID,\\\\\\\\
hInstance, NULL
mov hwndEdit, eax ;сохраним handle редактора
invoke SetFocus, hwndEdit ;дадим ему фокус ввода с клавиатуры
;подготовим структуру для чтения файла
mov ofn.lStructSize, SIZEOF ofn ;размер структуры
push hWnd
pop ofn.hWndOwner ;handle окна-родителя
push hInstance
pop ofn.hInstance ;handle экземпляра программы
mov ofn.lpstrFilter, OFFSET FilterString ;адрес строки-фильтра
mov ofn.lpstrFile, OFFSET buffer ;адрес строки, куда запишется имя файла
mov ofn.nMaxFile, MAXSIZE ;размер буфера для имени файла
.ELSEIF uMsg==WM_SIZE ;приходит во время изменения размера основного окна
mov eax, lParam ;новые размеры окна
mov edx, eax
shr edx, 16 ;высота окна
and eax, 0ffffh ;ширина окна
invoke MoveWindow, hwndEdit, 0, 0, eax, edx, TRUE ;растягиваем редактор по всему основному окну
.ELSEIF uMsg==WM_DESTROY ;приходит, когда надо закончить работу
invoke PostQuitMessage,NULL ;посылаем ноль в очередь сообщений
.ELSEIF uMsg==WM_COMMAND ;приходит после выбора пункта меню, нажатия на кнопки и т.д.
mov eax, wParam ;идентификатор команды
.if lParam==0 ;если не было нотификации...
.if ax==IDM_OPEN ;команда "open"
mov ofn.Flags, OFN_FILEMUSTEXIST or \\\\\\\\ ;дооформляем поле структуры флагами
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\\\\\\\\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn ;вызываем стандартную функцию выбора имени файла для открытия
.if eax==TRUE ;если что-то выбрано,
;то открываем файл с именем из buffer
invoke CreateFile, ADDR buffer,\\\\\\\\
GENERIC_READ or GENERIC_WRITE ,\\\\\\\\
FILE_SHARE_READ or FILE_SHARE_WRITE,\\\\\\\\
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE,\\\\\\\\
NULL
mov hFile, eax ;сохраним handle файла
;выделим буфер в памяти для чтения файла
invoke GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, MEMSIZE ;запросим блок памяти
mov hMemory, eax ;сохраним handle блока
invoke GlobalLock, hMemory ;"захватим" блок памяти
mov pMemory, eax ;сохраним указатель на буфер в блоке памяти
;прочитаем файл в буфер максимум MEMSIZE-1 байт
invoke ReadFile, hFile, pMemory, MEMSIZE-1, ADDR SizeReadWrite, NULL
;отправим содержимое буфера в редактор для отображения
invoke SendMessage, hwndEdit, WM_SETTEXT, NULL, pMemory
invoke CloseHandle, hFile ;закрываем файл
invoke GlobalUnlock, pMemory ;разблокируем блок памяти
invoke GlobalFree, hMemory ;освободим блок памяти
.endif ;eax=TRUE
invoke SetFocus, hwndEdit ;дадим фокус ввода редактору
.elseif ax==IDM_SAVE ;команда "save"
mov ofn.Flags,OFN_LONGNAMES or\\\\\\\\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetSaveFileName, ADDR ofn ;вызываем стандартную функцию выбора имени файла для сохранения
.if eax==TRUE ;если что-то выбрано
;то открываем файл с именем из buffer
invoke CreateFile, ADDR buffer,\\\\\\\\
GENERIC_READ or GENERIC_WRITE ,\\\\\\\\
FILE_SHARE_READ or FILE_SHARE_WRITE,\\\\\\\\
NULL, CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE,\\\\\\\\
NULL
mov hFile, eax ;сохраним handle файла
;выделим буфер в памяти для чтения содержимого редактора и записи в файл
;строки без комментариев полностью аналогичны при "open"
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,MEMSIZE
mov hMemory, eax
invoke GlobalLock, hMemory
mov pMemory, eax
;получим данные из редактора (в EAX получим реальную длину)
invoke SendMessage, hwndEdit, WM_GETTEXT, MEMSIZE-1, pMemory
;пишем в файл
invoke WriteFile, hFile, pMemory, eax, ADDR SizeReadWrite, NULL
invoke CloseHandle, hFile
invoke GlobalUnlock, pMemory
invoke GlobalFree, hMemory
.endif ;eax=TRUE
invoke SetFocus, hwndEdit
;все остальные команды приведут к уничтожению окна и завершению работы
.else
invoke DestroyWindow, hWnd
.endif ;анализ команды сообщения WM_COMMAND в AX
.endif ;if lParam==0 сообщения WM_COMMAND
.ELSE ;все остальные сообщения отрабатываюся стандартно
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.ENDIF ;анализ uMsg
xor eax, eax ;сообщаем, что нужные нам сообщения нами обработаны
ret
WndProc endp
end start ;задаем точку входа
|  |