Masm::api
- получить путь до текущей директории [директория программы]
- получить список всех файлов и подкаталогов директории - как лучше пройтись по всем файлам директории, рекуривно? Кстати, в асме рекурсию никто не отменял - как с ней работать - как в языках высокого уровня?
- переименовать файл
Я недавно в асме.. мне нужно несколько действий осуществить, подозреваю что они через API реализуются.. помогите пожалуйста:
- получить путь до текущей директории [директория программы]
- получить список всех файлов и подкаталогов директории - как лучше пройтись по всем файлам директории, рекуривно? Кстати, в асме рекурсию никто не отменял - как с ней работать - как в языках высокого уровня?
- переименовать файл
- invoke GetCurrentDirectory, MAX_PATH, offset buffer
MAX_PATH - 260, число символов в буфере.
buffer - буфер, выделенный в секции .data?(UDATASEG), как buffer db MAX_PATH+1 dup(?)
А вообще, если нужна директория, откуда программа запущена, то лучше извлечь её из коммандной строки, а то вдруг после запуска она поменяется, или в ярлыке на программу будет написана другая.
- вызвать функцию FindFirstFile.
- сохранить хэндл поиска.
- вызывать функцию FindNextFile, пока она не вернёт 0. В параметре cFileName будет имя найденного файла. Его то и надо в свой буфер копировать. И никакой рекурсии, если не потрошить подкаталоги. И ничего тут сложного нет - просто вызываешь процедуру из неё самой, при этом локальные переменные(в стеке) сохраняются, а вот глобальные - нет.
- функция MoveFile, первый параметр - путь к файлу, второй - новое имя.
Удачи в изучении асма...
На будующее - пожалуйста указывайте библиотеки, в которых эти функции.
Еще несколько вопросов..
Часто в примерах встречаю исключающее или самого себя, т .е. xor eax,eax - что это значит? Обнуление стека? Зачем используется?
Почему некоторые хэндлы передаются через стек, а не напрямую через mov?
И вот еще - shl eax,16/shr eax,16 - логического смещение, причем очень часто встречаю на 16.. почему? Что это значит?
В каких случая нужно использовать MainProc, а в каких DlgProc - в чем разница между окнами?
Где можно взять хорошую полную документацию по MASM? Желательно руссифицированную..
Спасибо, я попробую..
На будующее - пожалуйста указывайте библиотеки, в которых эти функции.
Вроде все эти функции экспортируются из kernel32.dll.
Часто в примерах встречаю исключающее или самого себя, т .е. xor eax,eax - что это значит? Обнуление стека? Зачем используется?
xor - логическое исключающее или. Эта команда побитово обрабатывает первый параметр, сравнивая его со вторым. Если соответствующие биты у обоих параметров одинаковые, то результат - 0, если разные - то 1. При xor eax, eax - операнды одинаковые, есстественно все соотвествующие биты одинаковые, поэтому регистр eax обнуляется. Это лучший способ обнулить регистр, т.к. команды xor и mov одинаково спариваются на Pentium, и генерируют одинаковое число микроопераций на PPro - P III, но хор на 3 байта короче(mov eax, 0 - 5 байт, а xor eax, eax - 2 байта).
Да... В Windows API используется передача по соглашению stdcall - все параметры передаются функции в стеке в обратном порядке, и фуекция сама очищает стек. Вот вызов ShowWindow будет выглядеть так:
push SW_SHOWNORMAL
push hwnd
call ShowWindow
Именно в это превратится invoke ShowWindow, hwnd, SW_SHOWNORMAL. Есть ещё два распространённых способа - cdecl и fastcall. cdecl аналогичен stdcall, но функция не очищает стек, т.е. параметры будут болтаться в стеке. Если бы функция ShowWindow была бы cdecl, то после её вызова пришлось бы писать add esp, 8(освободить стек от двух параметров. Каждый параметр - 4 байта). Но в некоторых случаях это удобно. Допустим, что функция IsWindow - cdecl. Тогда можно вызвать две функции подряд:
push hwnd
call IsWindow
call IsIconic
add esp, 4
Но все функции Windows - stdcall, поэтому можно забыть о add esp, XXX и заносить параметры в стек каждый раз. fastcall отличается от других. Там первый параметр в ecx, следующий в edx, остальные в стеке в обратном порядке. Функция сама очищает стек.
при shr eax, 16 старшая часть eax обнуляется, а в младшую(регистр ax) попадает старшая. При shl всё наоборот.
DlgProc - процедура диалогового окна. Оно создаётся как ресурс и его не надо создавать функцией CreateWindowEx.
[color=FF0000]очень хороная документация по асму для Windows[/color]
AppName db "SOMEName",0
.code
...........
invoke CharLower, AppName
invoke MessageBox, NULL, title, eax, MB_OK
...........
Что здесь неправильно? Он компилится, но мессаджбокс возвращает совсем не "somename" а что-то посимвольное..
Вот мой код:
AppName db "SOMEName",0
.code
...........
invoke CharLower, AppName
invoke MessageBox, NULL, title, eax, MB_OK
...........
Что здесь неправильно? Он компилится, но мессаджбокс возвращает совсем не "somename" а что-то посимвольное..
Лучше нашиши не AppName, а offset AppName или addr AppName(При вызове CharLower), т.к. ты передаешь на указатель на строку, а её первые четыре символа.
Есть еще несколько вопросов..
Как на время изменить курсор на песочные часы, а потом вернуть в исходное состояние (в диалоговом окне, DlgProc)?
Как Disabled'ить кнопку и Enabled'ить ее обратно? Без DRAWITEMSTRUCT никак?
Как определить существует ли дириктория по указанному пути? Очень надо..
Как найти подстроку в строке? Первое или последнее вхождение.. Вобщем нужно определить в тексте Edit контрола наличие Wildcards (в пути). Wildcards методов findfirst/findnext могут быть использованы только в секции имени файла или ими же можно задавать и путь (т.е. C:\dir\a?c\*.ext)?
Спасибо за помощь.. в моей голове все начинает проясняться.
Есть еще несколько вопросов..
Как на время изменить курсор на песочные часы, а потом вернуть в исходное состояние (в диалоговом окне, DlgProc)?
Как Disabled'ить кнопку и Enabled'ить ее обратно? Без DRAWITEMSTRUCT никак?
Как определить существует ли дириктория по указанному пути? Очень надо..
Как найти подстроку в строке? Первое или последнее вхождение.. Вобщем нужно определить в тексте Edit контрола наличие Wildcards (в пути). Wildcards методов findfirst/findnext могут быть использованы только в секции имени файла или ими же можно задавать и путь (т.е. C:\dir\a?c\*.ext)?
- Курсор изменяет функция SetCursor. Её нужно всунуть в обработчик события WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_RBUTTONDOWN.
- Функция EnableWindow(смотри описание)
- Это определяется функцией FindFirstFile, только надо указать в аттрибутах файла, чтобы искалась папка.
- Напиши сам такую функцию, это не сложно. А насчёт wild символов - не помню. Это можно и самому попробовать.
Есть ли API функция, чтобы по полному пути получить путь к директории (не имя)? Если нет, то как это можно реализовать? Я вообще не представляю как работать со строками в ASM. По идее надо найти последнее вхождение слеша в пути и взять строку от начала до этого вхождения. Но как это сделать?
Второй вопрос тоже по строкам - как можно прочесть последний или первый (или любой другой по номеру) символ в строке?
Я извиняюсь, но у меня еще 2 вопроса.. надеюсь последние по этой теме.
Есть ли API функция, чтобы по полному пути получить путь к директории (не имя)? Если нет, то как это можно реализовать? Я вообще не представляю как работать со строками в ASM. По идее надо найти последнее вхождение слеша в пути и взять строку от начала до этого вхождения. Но как это сделать?
Второй вопрос тоже по строкам - как можно прочесть последний или первый (или любой другой по номеру) символ в строке?
Нет такой API функции. Надо искать последнее вхождение "\". Например через repne scasb/scasw.
Символ можно прочитать так. допустим edi - указатель на строку. mov al, [edi] - читать первый символ(ASCII), mov al, [edi+eax] читать символ под номером eax.
DIR db MAX_PATH dup(?)
...
LOCAL len:DWORD
...
invoke lstrlen, ADDR PATH
mov len, eax
STD ;в обратном порядке
MOV AL, '\' ;символ поиска
LEA DI, PATH+len-1 ;здесь нужен указатель на конец строки? как правильно?
MOV CX, len ;тут как? нужен same size
REPNE SCASB
JNE NOTFOUND ;если символ не найден
...
;если найден, как поместить строку с ее начала до найденной позиции в DIR
...
NOTFOUND:
...
mov ecx, eax
std
mov al, '\'
lea edi, [ecx+offset PATH-1]
repne scasb
jnz NOTFOUND
;символ найден
;в ecx - сколько перед разделителем символов.
;копировать можно функцией memmove из ntdll.dll(ну ;если windows NT) или писать свою функцию.
Я заметил.. а почему? DF на что-то еще влияет?
Еще несколько вопросов..
Помогите со ссылками (HyperLink) разобраться. Я сделал STATIC control и перехват клика на нем.
Как можно изменить размер/цвет текста и стили надписи в STATIC control (например, underline)?
Где устанавливается курсор при наводе на ссылку? В WM_MOUSEMOVE?:
invoke LoadCursor, NULL, IDC_HAND
invoke SetCursor, eax
Как сделать так, чтобы IDC_HAND был бы только у STATIC control, а не у всего окна?
.............
CONTROL "visit it", IDC_URL, "STATIC", SS_SIMPLE | SS_NOTIFY, 98, 13, 40, 7
.............
.asm
.............
.data
open db "open",0
url db "http:\\site.com",0
.code
.............
.IF uMsg==WM_COMMAND
mov eax, wParam
.IF lParam!=0
mov edx,wParam
shr edx,16
.IF dx==STN_CLICKED
.if ax==IDC_URL
invoke ShellExecute, hWnd, ADDR open, ADDR url, 0, 0, SW_SHOWNORMAL
.endif
.endif
.endif
.ENDIF
.............
и еще...
Глупый вопрос наверное.. но все же мне надо понять.
Как считать определенные процессы - к примеру итерации цикла.
counter db ?
.............
.code
.............
inc counter
.............
Но как потом вывести результат в читаемом виде? Т.е. я делаю:
invoke MessageBox, NULL, ADDR counter, ADDR AppName, MB_OK
и вижу не число. И можно ли выводить в MessageBox'e значения регистров (в целях отладки)?