Консультация № 171960
07.09.2009, 02:16
0.00 руб.
0 4 0
Доброй ночи, Уважаемые Эксперты. Решил написать программу на асме, которая используя функцию FindFirst в первый попавшийся txt файл в текущей директории производит запись. К сожалению появляется ошибка, мол неправильный хэндл.
Если не трудно исправьте ошибку в коде.
Благодарю за внимание.

Приложение:
includelib import32.lib
.386
.model flat

extrn ExitProcess : near
extrn CreateFileA : near
extrn MessageBoxA : near
extrn CreateFileMappingA : near
extrn UnmapViewOfFile : near
extrn CloseHandle : near
extrn MapViewOfFile : near
extrn FindFirstFileA : near
extrn FindNextFileA : near
extrn GetLastError : near

OPEN_EXISTING = 3
FILE_ATTRIBUTE_NORMAL = 80h
GENERIC_READ = 80000000h
GENERIC_WRITE = 40000000h
PAGE_READWRITE = 00000004h
FILE_MAP_WRITE = 02h or 04h

;--------------------------------------
.data
FileName db '000.txt', 0
HFile dd ?
HFM dd ?
addr_of_the_mapped_view dd ?
hFF dd ?

szTitle db '123',0
szMessage db 'ERROR',0
string db '74'
len equ $-string

WFD32:
FAtribute dd 0
FCreationTime dd 0,0
FLastAcsTime dd 0,0
FLWTime dd 0,0
FSizeH dd 0
FSizeL dd 0
FReserve dd 0,0
FName db 260 dup (0)
AltFName db 13 dup (?)

FNSearch db '*.txt',0

;--------------------------------------
.code
_start:
call FINDFIRST




push 00h
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 00h
push 00h
push GENERIC_READ or GENERIC_WRITE
push offset FName
call CreateFileA
call GetLastError
cmp eax,-1
je ERROR
mov HFile,eax

CREATE_MAPPING:
xor eax,eax
push eax ;lpName
push eax ;dwMaximumSizeLow
push eax ;dwMaximumSizeHigh
push PAGE_READWRITE
push eax
push dword ptr FName
call CreateFileMappingA
call GetLastError
test eax,eax
jz ERROR
mov HFM, eax

MAP:
xor eax,eax
push eax ;dwNumberOfBytesToMap
push eax ;dwFileOffsetLow
push eax ;dwFileOffsetHigh
push FILE_MAP_WRITE ;dwDesiredAccess
push HFM
call MapViewOfFile
test eax,eax
jz ERROR
mov addr_of_the_mapped_view,eax
mov edx,20

ACT:

mov esi,offset string
mov edi,eax
inc eax
inc eax
mov ecx,len
rep movsb
dec edx
test edx,edx
jz UNMAP
jmp ACT

UNMAP:
push addr_of_the_mapped_view
call UnmapViewOfFile

CLOSEMAP:
push HFM
call CloseHandle

ClOSEF:
push HFile
call CloseHandle

jmp Exit

ERROR:
xor eax,eax
push 30h
push offset szTitle
push offset szMessage
push eax
call MessageBoxA


Exit:
push 0
call ExitProcess

FINDFIRST proc near

push offset WFD32
push offset FNSearch
call FindFirstFileA
call GetLastError
cmp eax,-1
je ERROR
mov hFF,eax
ret

FINDFIRST ENDP

FINDNEXT proc near

push offset WFD32
push dword ptr hFF
call FindNextFileA
test eax,eax
jz ERROR
ret

FINDNEXT ENDP
end _start

Обсуждение

давно
Старший Модератор
31795
6196
07.09.2009, 15:05
общий
VIXEN555:
Цитата: Ваш код
call FindFirstFileA
call GetLastError
cmp eax,-1
je ERROR

Вы неправильно используете функцию GetLastError.
Функция FindFirstFile возвращает дескриптор поиска в ЕАХ, а Вы вместо проверки была ошибка или нет, затираете его вызовом функции GetLastError. Этот участок у Вас должен быть приблизительно таким:
Код:
		push	offset dwFindAttr;структура
push offset dbFindMask;маска поиска
call FindFirstFileA;21Ѕ:°Ѕ=4µЅ
;проверяем была ли ошибка
cmp eax,-1;INVALID_HANDLE_VALUE
jnz noErrorFindFirst
;тут Вы обрабатываете саму ошибку получая её код вызовом GetLastError
call GetLastError
. . .
. . .
;find is succeeds eax=hFindFile
noErrorFindFirst:
mov hFindFile,eax;handle for current find round
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
07.09.2009, 23:29
общий
Зенченко Константин Николаевич:
Благодарю за исправление ошибки. Если правильно понял, то для поиска одного файла достаточно FindFirstFile, а если необходимо найти все файлы в текущей директории, то функцию FindNextFile необходимо зациклить?
давно
Старший Модератор
31795
6196
08.09.2009, 15:24
общий
VIXEN555:
Давно уже писал поисковик обходящий текущий каталог и все подкаталоги.
Код:
.386
.model flat
includelib ..\Tasm\TASM5\LIB\imp32i.lib
MAX_PATH equ 260
extrn ExitProcess:near
extrn MessageBoxA:near
extrn GetCurrentDirectoryA:near
extrn SetCurrentDirectoryA:near
extrn FindFirstFileA:near
extrn FindNextFileA:near
extrn FindClose:near
extrn GlobalAlloc:near
extrn GlobalLock:near
extrn GlobalFree:near
extrn GetLastError:near
.data
dbFindTitle db 'Compare files',0
;mask for find
dbFindMask db '*.*',0
;
dbErrorLongName db 'error:very log name',0
dbErrorAllocMemory db 'error:alloc memory',0
dbErrorSetFolder db 'error:set current folder',0
dbErrorGetFolder db 'error;get current folder',0
dbErrorFindClose db 'error:find close',0
dbErrorFindFirst db 'error:find first file',0
dbErrorFindNext db 'error:find next file',0
dbErrorDispose db 'error:dispose memory',0
StopFind db 'is stop',0
GoJob db 'show mast go on',0
;data for folder
;data for find
hFindFile dd ?
lpFirstFolder dd ?
lpFirstFile dd ?
dwFindAttr dd ?;file attributes
dd ?,?;time of file creation
dd ?,?;time of last file access
dd ?,?;time of last write access
dwHighSize dd ?;high-order word of file size
dwLowSize dd ?;low-order word of file size
dd ?;(reserved)
dd ?;(reserved)
dbFindName db MAX_PATH dup(?);matching file name
dbFindAName db 14 dup(?);8.3 alias name
lpThisFolder dd ?
lpLastFolder dd ?
lpLastFile dd offset lpFirstFile
.code
start: cld
;---------------
;получаем текущую директорию
push offset dbFindName;указатель куда будет записан путь к директории
push MAX_PATH;максимальная длина
call GetCurrentDirectoryA;21Н:АН=47Н
;проверяем ошибку работы функии
or eax,eax
jnz noErrorGetFolder
mov edx,offset dbErrorGetFolder
jmp ErrorMessage
;начинаем работать
noErrorGetFolder:
mov ecx,eax
mov lpThisFolder,eax
add ecx,08
call GetMemory;
mov ecx,lpThisFolder
mov edi,eax
mov esi,offset dbFindName
mov lpFirstFolder,eax
mov lpThisFolder,eax
mov lpLastFolder,eax
xor eax,eax
stosd
mov eax,ebx
stosd
;begin copy
rep movsb
xor eax,eax
stosb
;
;---------------BEGIN FIND IN THIS FOLDER
;
;поиск первого файла в каталоге
beginFind: push offset dwFindAttr;аттрибуты для поиска
push offset dbFindMask;маска поиска
call FindFirstFileA;21Н:АН=4ЕН
;контроль ошибки
cmp eax,-1;INVALID_HANDLE_VALUE
jnz noErrorFindFirst
mov edx,offset dbErrorFindFirst
jmp ErrorMessage
;find is succeeds eax=hFindFile
noErrorFindFirst:
mov hFindFile,eax;handle for current find round
;проверяем это папка или файл
findNext: mov eax,dwFindAttr
test eax,10h;FILE_ATTRIBUTE_DIRECTORY
jz isFileNow;если не папка переходим на обработку файлов
;---------------BEGIN FOLDER SECTION
;это папка
mov al,dbFindName
cmp al,'.'
jz skipFolder
call CheckLongName;контрольдлины файла
;calculation for memory reqest
mov esi,lpThisFolder
lodsd
call checkLong
add ecx,08
call GetMemory
mov esi,lpLastFolder
mov edi,eax
mov [esi],eax
mov lpLastFolder,eax
xor eax,eax
stosd ;save NULL in cuurent folder block
mov eax,ebx
stosd ;save alloc handle for dispose
mov esi,lpThisFolder
lodsd
;copy current folder path
copyPath: lodsb
stosb
or al,al
jnz copyPath
dec edi
mov al,'\'
stosb
nameCopy: mov esi,offset dbFindName
;---------------END FOLDER SECTION
;
;---------------BEGIN FILE AND FOLDER SECTION
;copy folder name
copyName: lodsb
stosb
or al,al
jnz copyName
;in memory block save new null(4)+new element for find
skipFolder: push offset dwFindAttr
push hFindFile
call FindNextFileA
;check last error
or eax,eax
jnz findNext
;---------------END FILE AND FOLDER SECTION
;
;---------------CHECK FIND ERROR
call GetLastError
cmp eax,18;ERROR_NO_MORE_FILES
jz noErrorFindNext
mov edx,offset dbErrorFindNext
jmp ErrorMessage
;close this find round
noErrorFindNext:
push hFindFile
call FindClose
;check error
or eax,eax
jnz noErrorFindClose
mov edx,offset dbErrorFindClose
jmp ErrorMessage
;change current folder
noErrorFindClose:
mov esi,lpThisFolder
mov eax,[esi]
;check next folder is not NULL
or eax,eax
jnz noFindStop
jmp FindStop
noFindStop: mov lpThisFolder,eax
mov esi,eax
lodsd;skip next pointer
lodsd;skip handle alloc
push esi
call SetCurrentDirectoryA
or eax,eax
jnz beginFind
;---------------END FIND IN THIS FOLDER
;is error set new curent directory
mov edx,offset dbErrorSetFolder
jmp ErrorMessage
;
;---------------BEGIN FILE SECTION
isFileNow: call CheckLongName
add ecx,20
call GetMemory
mov edi,eax
mov esi,lpLastFile
mov [esi],edi
mov lpLastFile,eax
xor eax,eax
stosd;+0
mov eax,ebx
stosd;+4
mov eax,lpThisFolder;pointer to directory
stosd;+8
mov eax,dwHighSize
stosd;+12
mov eax,dwLowSize
stosd;+16
jmp nameCopy
;---------------END FILE SECTION
;
;---------------BEGIN COMPARE SECTION
FindStop:

;---------------BEGIN PROCEDURE SECTION
;
;подпрограмма получения свободной памяти
GetMemory: shr ecx,4;выравнивае на 16
inc ecx
shl ecx,4
;получаем память
push ecx;размер запрашиваемой памяти
push 2;GMEM_MOVEABLE
call GlobalAlloc
;контрольошибки резервирования
or eax,eax
jz ErrorAllocMemory
;переводим указатель в адрес
mov ebx,eax
push eax
call GlobalLock
jz ErrorAllocMemory
ret
ErrorAllocMemory:
mov edx,offset dbErrorAllocMemory
jmp short ErrorNext
;
;контроль длины имени
CheckLongName: mov esi,offset dbFindName
xor ecx,ecx
checkLong: lodsb
inc ecx
;контроль очень длиного имени
cmp ecx,MAX_PATH
jg ErrorLongName
or al,al
jnz checkLong
ret
ErrorLongName: mov edx,offset dbErrorLongName
ErrorNext: pop edi
;error message and exit
ErrorMessage: call OutMessage
;
;dispose all alloc memory in current process
;освоождаем всю занятую память
mov esi,lpFirstFolder
call doDispose;под папки
mov esi,lpFirstFile
call doDispose;под файлы
push 0
call ExitProcess;выход
;выводим сообщение
OutMessage: push 0
push offset dbFindTitle
push edx
push 0
call MessageBoxA
ret
;только для котроля
ShowJob: mov esi,lpFirstFile
jobNow: mov edx,20
or esi,esi
je stopExit
add edx,esi
call OutMessage
mov esi,[esi]
jmp jobNow
stopExit: ret
;освобождаем всю занятую память
doDispose: mov eax,[esi+4]
mov edi,[esi]
push eax
call GlobalFree
or edi,edi
jz goDispose
mov esi,edi
or eax,eax
jz doDispose
mov edx,offset dbErrorDispose
call OutMessage
goDispose: ret
end start

Он создавал в памяти два динамических списока: путей каталогов и всех файлов. После этого сортировал по размеру все файлы и начинал сравнение с целью поиска разноименных одинаковых файлов и для последующего их удаления. Блок сравнения я вырезал, а сам поисковик смотрите выше.
Думаю основные принципы Вам будут полезны.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
08.09.2009, 16:36
общий
Зенченко Константин Николаевич:
Благодарю за исходник, обязательно его изучу в целях понятия работы основного алгоритма. Однако при запуске появляется ошибка "error:alloc memory", а затем вылазит фатальная ошибка аварийного завершения программы.
Алгоритм в части поиска файлов рабочий?
Форма ответа