Макросы и стандартные диалоги Windows
Доброго времени суток, уважаемые подписчики.
Как видно из заголовка сегодняшнего урока, я решил обратить ваше внимание на одно из приемуществ ассемблера, макросы. Наверняка многие из Вас уже знают, что это такое, но одно дело знать, а другое использовать. А использовать правильно - это ещё труднее. В зтом уроке мы поговорим об основах написания макросов и сделаем пару примеров, которые будем использовать в нашей программе. Макрос - это часть программы, которая ассемблируется каждый раз, когда компилятор встречает, причём этот код может получать параметры и выполняться в зависимости от них! Например мокрос обнуления регистра директивой xor может быть очень удобен, давайте создадим файл makros.inc и запишем в него следующий макрос:
null macro param1
xor param1,param1
endm
|
после добавление в файл с кодом программы строки include macros.inc команда null eax будет интерпритироваться как xor eax,eax, null ebx - xor ebx,ebx и т.д. Вы спросите нафиг это надо, ведь и так не было так трудно написать, однако если кто-то не очень соображающий в ассемблере увидит xor eax,eax, он в 99 случаях из ста непоймёт что это такое, а null eax заставит его подумать, что происходит обнуление еах. Это вторая полезность макросов, они делают программу более понятной. Пока макросы нам не особо нужны, но при написании более серьёзных программ они начинают играть серьёзную роль.
Другой вопрос, который я хотел бы рассмотреть сегодня, это использование стандартных диалогов Windows. В принципе, мы уже сталкивались с этим явлением, так как MessageBox тоже является стандартным диалогом. Сегодня мы познакомимся со стандартным диалогом открытия файла, который вызывается функцией Windows GetOpenFileName, которая получает один(!) параметр, offset структуры OPENFILENAME, которую мы сейчас и рассмотрим:
OPENFILENAME struc
lStructSize dd ? ;Размер структуры, используется для определения версии структуры
hwndOwner dd ? ;handle окна-родителя
_hInstance dd ? ;handle приложения, из которого происходит запуск
lpstrFilter dd ? ;указатель на фильтры поиска
lpstrCustomFilter dd ? ;указатель на вторичные фильтры поиска
nMaxCustFilter dd ? ;кол-во символов в lpstrCustomFilter
nFilterIndex dd ? ;номер фильтра, устанофленного по умолчанию
lpstrFile dd ? ;указатель на буфер для полного имени файла
nMaxFile dd ? ;размер буфера lpstrFile
lpstrFileTitle dd ? ;указатель на буфер для имени файла без диретории
nMaxFileTitle dd ? ;размер буфера lpstrFileTitle
lpstrInitialDir dd ? ;Указатель на директорию по умолчанию
lpstrTitle dd ? ;Указатель на строку, которая будет помещена в заголовок
Flags dd ? ;Битовые флаги, определяющие работу диалога
nFileOffset dw ? ;указатель на имя файла
nFileExtension dw ? ;указатель на расширение файла
lpstrDefExt dd ? ;расширение по умолчанию
lCustData dd ? ;Пока нам не нужно
lpfnHook dd ? ;Пока нам не нужно
lpTemplateName dd ? ;Пока нам не нужно
OPENFILENAME ends
|
Многие параметры я оставил без объяснения так как мы ещё не умеем использовать операции для которых они существуют.
Теперь дополним нашу программу:
include kernel32.inc
include user32.inc
include def32.inc
include comdlg32.inc ;Добавляем функции библиотеки стандартных диалогов
include macros.inc ;наши макросы (пока один;)
MAXFILENAME equ 260
.386
.model flat
.data
error db 'Ошибка',0
error1 db 'Файл не найден,0
error2 db 'Заданный файл не существует',0
filters db 'Text files',0,'*.txt',0 ;Фильтры поиска
db 'All files',0,'*.*',0,0
fileName dd 0
programHandle dd 0
fileHandle dd 0
memoryHandle dd 0
memoryOffset dd 0
SizeRW dd 0
filename_ db MAXDILENAME dup(0)
ofn OPENFILENAME<size ofn,?,?,offset filters,?,?,?,offset filename_,MAXFILENAME,0,?,0,?,?,?,?,0,?,?,?>
.code
_start:
null ebx ;используем наш макрос
push ebx
call GetModuleHandle
mov programHandle,eax
call GetCommandLine
mov edi,eax
mov al,20h
mov ecx,-1
repne scasb
cmp byte ptr [edi],bl
jne File_OK
mov ofn.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_EXPLORER
push offset ofn
call GetOpenFileName ;Вызваем диалог
test eax,eax ;Если не "отмена", то не ноль
jz program_end
mov fileName,offset filename_ ;для совместимости с уже написаным
File_OK:
repe scasb
dec edi
mov esi,edi
mov fileName,edi
push ebx
push FILE_ATTRIBUTE_ARCHIVE
push OPEN_EXISTING
push ebx
push FILE_SHARE_READ
push GENERIC_READ
push esi
call CreateFile
test eax,eax
jnz file_opened_OK
mov eax,offset error2
jmp program_error
file_opened_OK:
mov fileHandle,eax
push ebx
push eax
call GetFileSize
mov edi,eax
push eax
push GMEM_MOVEABLE or GMEM_ZEROINIT
call GlobalAlloc
mov memoryHandle,eax
push eax
call GlobalLock
mov memoryOffset,eax
push ebx
push offset SizeRW
push edi
push eax
push fileHandle
call ReadFile
push fileHandle
call CloseHandle
call CheckSymbol
push ebx
push FILE_ATTRIBUTE_ARCHIVE
push TRUNCATE_EXISTING
push ebx
push FILE_SHARE_WRITE
push GENERIC_WRITE
push fileName
call CreateFile
push ebx
push offset SizeRW
push edi
push memoryOffset
push FileHandle
call WriteFile
push fileHandle
call CloseHandle
program_end:
push memoryHandle
call GlobalUnlock
push memoryHandle
call GlobalFree
push ebx
call ExitProcess
program_error:
push MB_IconWarning
push offset error
push eax
push ebx
call MessageBox
jmp program_end
CheckSymbol proc
push edi
mov al,'s'
mov ecx,edi
inc ecx
mov edi,memoryOffset
loop_check:
repne scasb
test ecx,ecx
jz end_check
mov byte ptr [edi-1],'$'
jmp loop_check
end_check:
pop edi
ret
CheckSymbol endp
end _start
|
Следующие файлы Вы можете скачать к этому уроку:
0012asm - код программы
0012exe - компиляторы и сама программа
0012inc - файлы дополнения
0012lib - библиотеки импорта
На сегодня это всё. Если есть какие вопросы, пишите, обязательно отвечу.. Пишите, Dark_Lord@RusFAQ.ru, Dark_Lord@land.ru.
Сайт управляется системой uCoz
|