News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

FindNextFile Bug?

Started by ragdog, October 13, 2010, 01:29:18 PM

Previous topic - Next topic

ragdog

Hi

I Programming a little with FindFirstFile and FindNextFile now have i a problem with my counter.
I add a counter and push and pop ecx to the stack.
Use i the register ecx works my counter not correct replace i this to esi or other register,
works this correct why?

I have look in the kernel32.dll (win7) with Ollydbg at 75EAA977
And see the ecx if not pushed or poped !!

If this an Bug of FindNextFile by Windows 7?

Here is my code


Scan proc uses edi ecx
LOCAL buffer[MAX_PATH]:BYTE
LOCAL wfd:WIN32_FIND_DATA
LOCAL hwfd:DWORD

invoke lstrcpy,addr buffer,addr hPath
invoke lstrcat,addr buffer,CTEXT ("/*.*")
invoke FindFirstFile,addr buffer,addr wfd
.if eax!=INVALID_HANDLE_VALUE
mov hwfd,eax
xor ecx,ecx
    .while (eax!=0) && (ecx<3)
               lea   edi,wfd.cFileName
    invoke   AddItem,edi,1
               inc   ecx
    invoke   FindNextFile,hwfd,addr wfd
        .endw
;No more matches, close handle
invoke FindClose,hwfd
.endif
ret
Scan endp



Greets,

evlncrn8

the api calls probably destroy the ecx register.. push it before the api call and pop it after...

and i think...



xor ecx,ecx  ; ecx is zero here, making the code below useless as ecx will be zero and definately less than 3...

    .while (eax!=0) && (ecx<3)



is wrong..

box



xor ecx,ecx  ; ecx is zero here, making the code below useless as ecx will be zero and definately less than 3...

    .while (eax!=0) && (ecx<3)



This is fine, it's just FindNextFile trashing ecx. Most win API functions only preserve ebx/esi/edi I believe.

ragdog

@evlncrn8

xor ecx,ecx  ; This fill ecx with zero

    .while (eax!=0) && (ecx<3) ;if ecx less than 3 inc ecx . if ecx greater then jmp out of the loop
     ...
      ..
      inc ecx
    .endw

Yes this api destroy the ecx register ,and use ecx without push ecx in to stack or pop ecx from stack


ToutEnMasm


preservation rule
only EBX EDI ESI  are returned without changes.
Your proc must do the same thing     (unproc PROC uses ebx esi edi machin:DWORD)

dedndave

Quotepreservation rule
only EBX EDI ESI  are returned without changes.
oh - and EBP
oh - and the direction flag

ragdog

@ToutEnMasm

I understand not correct what you mean with it :'(

jj2007

Quote from: dedndave on October 13, 2010, 05:26:28 PM
oh - and the direction flag

That would be worth a test - try calling some APIs with the flag set :bg

RuiLoureiro

ragdog,
            Why to use ECX ? Why not EBX ?
            Replace ECX by EBX and try again. Is there a bug ?
Rui

Tedd

Quote from: ragdog on October 13, 2010, 05:57:57 PM
@ToutEnMasm
I understand not correct what you mean with it :'(
He means: when you call an API function, it may change the values in registers <EAX>, ECX, EDX, but not in EBX, ESI, EDI - so, if you need the values of eax/ecx/edx, you must save them yourself outside of the function call.
This is standard for (almost) all API functions.
No snowflake in an avalanche feels responsible.

ragdog

@RuiLoureiro

Yes i can use edi ebx or anything

I use always ecx as counter and have found this problem

This is a rule of thumb Mnemonics and i coding with it

EAX =Accumulator
EBX = Base
ECX = Counter
EDX =Destination

ESI = Source index
EDI = Destination index
EBP =Base Pointer
ESP =Stack Pointer
EIP =Instructions pointer
ESP = Stack pointer


Thanks Tedd

Quoteyou must save them yourself outside of the function call.

You mean before i call a api push my register to the stack?

Greets

Tedd

Quote from: jj2007 on October 13, 2010, 08:49:03 PM
Quote from: dedndave on October 13, 2010, 05:26:28 PM
oh - and the direction flag
That would be worth a test - try calling some APIs with the flag set :bg
I'd guess the notion isn't so much of preserving the direction flag as assuming it will, and should always be, cleared (string operations increment the index registers.) So, if a function internally sets it, it will 'restore' the value by clearing it again, even if it was in fact set to begin with.
No snowflake in an avalanche feels responsible.

Tedd

Quote from: ragdog on October 13, 2010, 10:12:25 PM
You mean before i call a api push my register to the stack?
Yes - but usually only for eax, ecx, edx.

Also, don't worry so much about the 'definitions' for the registers - they are all general purpose (except for a few cases) and can be used in any way.
No snowflake in an avalanche feels responsible.

ragdog


dedndave

i don't suggest saving and restoring the eflags register
only - if you set the direction flag, be sure and clear it before you call an API
and clear it when your function is complete
in fact, i had a case where sometimes the direction flag needed to be set and sometimes it didn't
i pushed the eflags register and popped it into a general register, then tested the state of the DF
if it was clear, i did nothing - if it was set, i cleared it with CLD
that seemed to work better than simply pushing and popping the eflags register
POPFD, CLD, and STD are slow instructions
        pushfd
        pop     eax
        test    ah,4
        jz      @F

        cld

@@: