Учебник по ассемблеру (ASM)
 

Ассемблер в примерах - Прошу прокомментировать строки программы

Вопрос:
Прошу прокомментировать строки программы

Ответ:
;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		;задаем точку входа


   Вперёд
   Содержание