flat assembler
Message board for the users of flat assembler.

Index > Windows > stack and recursion

Author
Thread Post new topic Reply to topic
Vasilev Vjacheslav



Joined: 11 Aug 2004
Posts: 392
Vasilev Vjacheslav 31 Dec 2004, 15:18
hello and happy new year! Smile

i have procedure that searching certain file on specified path (with recursion), before recursion i use 'pushad', after exit i use 'popad',
when i found file i wan't to exit from '_findfile' procedure and return to 'nop', but i return to popad - and it is normally. How to return to 'nop'? What i must do with stack

Code:
  

start:
     stdcall _findfile,szStartPath,szFileToFind,szBuffer
     nop     <- here i want return fast, after found file
     invoke ExitProcess,NULL

proc       _findfile, lpStartPath,lpFileToFind,lpBuffer
        .wfd       FINDDATA
 .szPath    rb MAX_PATH
      .szSubPath rb MAX_PATH
      .hFind     dd ?

 enter
       lea     edi,[.szPath]
       invoke  lstrcpy,edi,[lpStartPath]

       invoke  lstrlen,edi
 cmp     byte [edi+eax-1],"\"
     je      @F
  cmp     byte [edi+eax-1],"/"
      je      @F
  xor     esi,esi
     add     esi,05Ch
    mov     word [edi+eax],si
  @@:
      invoke  lstrcat,edi,szMask

      lea     esi,[.wfd]
  stdcall _zeromem,esi,sizeof.FINDDATA

    invoke  FindFirstFile,edi,esi
       or      eax,eax
     jl      .error_find

     mov     [.hFind],eax

  .while_start:
     lea     esi,[.wfd.cFileName]
        lodsw
       sub     esi,2

   cmp     ax,"."
    je      .next_file
  cmp     ax,".."
   je      .next_file

      lea     edi,[.wfd]
  mov     eax,[edi+FINDDATA.dwFileAttributes]

     test    ax,FILE_ATTRIBUTE_DIRECTORY
 je      .else

   lea     edi,[.szSubPath]
    push    edi
 stdcall _zeromem,edi,MAX_PATH
       mov     edi,[esp]
   lea     eax,[.szPath]
       invoke  lstrcpy,edi,eax
     invoke  lstrlen,edi
 mov     byte [edi+eax-3],0
  invoke  lstrcat,edi,esi
     pop     edi

     pushad
      stdcall _findfile,edi,[lpFileToFind],[lpBuffer]
     popad
       jmp     .next_file

  .found_file:
        lea     esi,[.szPath]
       mov     edi,[lpBuffer]

  invoke  lstrlen,esi
 mov     byte [esi+eax-3],NULL

   invoke  lstrcpy,edi,esi

 lea     esi,[.wfd.cFileName]
        invoke  lstrcat,edi,esi

                ; here i must do something with stack
                ; to get pointer to 'nop' and return

  jmp     .error_find

  .else:
     invoke  lstrcmpi,[lpFileToFind],esi
 or      eax,eax
     jz      .found_file

  .next_file:
        lea     edi,[.wfd]
  invoke  FindNextFile,[.hFind],edi
   or      eax,eax
     jg      .while_start

  .close_find:
      invoke  FindClose,[.hFind]

  .error_find:
        return
  endp    

_________________
[not enough memory]
Post 31 Dec 2004, 15:18
View user's profile Send private message Reply with quote
beppe85



Joined: 23 Oct 2004
Posts: 181
beppe85 31 Dec 2004, 22:20
If you figure out how to do this, you could have the fastest decent recursive compilers. OK, I guess I've figured out, but let's talk about the problem.

To return fast from a deeply recursive function, you at first need to unwind the stack, which is usually done by just ret-urning from the current procedure. So this would not be a 'fast return'.

Implementation direction(slowest-to-fastest):
- call/return(usual way)
- loop retriving calling-ebp and moving to esp, until the destination is reached.
- mantain a display-like structure in each routine, ie. an array with entries representing the caller's stack frame, plus return adresses. Recursive functions are to be special case'd.

Now that you know the ways to go, I hope you understand that the first give the best cost-benefit, and less error-prone, approach.

I've never implemented the last nor proved it correct, so I could not continue describing it. Hope someday I do this.

I propose you to do the following, on return: the callee, set CF(=0:not found; =1: found); the caller, check CF and ret if needed.

Code:
...
        stdcall _findfile,edi,[lpFileToFind],[lpBuffer]
        jc .ret_found

.found_file:
...
        jmp .ret_found
...

.close_find: 
        invoke  FindClose,[.hFind]
        jmp .ret_not_found

...
.ret_found:
        stc
        return
.ret_not_found: 
        clc
        return    


Hope this help, and thank you for the insight.

Happy new year for you too!
Post 31 Dec 2004, 22:20
View user's profile Send private message Reply with quote
Vasilev Vjacheslav



Joined: 11 Aug 2004
Posts: 392
Vasilev Vjacheslav 01 Jan 2005, 13:09
ok, i align the stack and works fine. I've tryed my method before, but there were mistakes with arithmethics

but i found other problem Confused after open FindFirstFile i must close handle (is that true?), when file is found there still open handles (iFiles contains number of open handles also number of un-returned recursion call)

Code:
format pe gui 4.0
entry start

include '%fasminc%\win32a.inc'

MAX_PATH                     = 260

section '.idata' data readable writeable

  szPath        db "c:\chat",0
  szFile        db "basic.mrc",0
  szMask        db "*.*",0

section '.udata' readable writeable

  szBuffer      rb MAX_PATH
  iFiles        dd ?

section '.code' code readable executable

  start:
        xor     eax,eax
        mov     [iFiles],eax
        stdcall _findfile,szPath,szFile,szBuffer
        invoke  ExitProcess,NULL

  proc  _findfile, lpStartPath,lpFileToFind,lpBuffer
        .wfd       FINDDATA
        .szPath    rb MAX_PATH
        .szSubPath rb MAX_PATH
        .hFind     dd ?

        enter
        lea     edi,[.szPath]
        invoke  lstrcpy,edi,[lpStartPath]

        invoke  lstrlen,edi
        cmp     byte [edi+eax-1],"\"
        je      @F
        cmp     byte [edi+eax-1],"/"
        je      @F
        xor     esi,esi
        add     esi,05Ch
        mov     word [edi+eax],si
  @@:
        invoke  lstrcat,edi,szMask

        lea     esi,[.wfd]
        stdcall _zeromem,esi,sizeof.FINDDATA

        invoke  FindFirstFile,edi,esi
        or      eax,eax
        jl      .error_find

        mov     [.hFind],eax

  .while_start:
        lea     esi,[.wfd.cFileName]
        lodsw
        sub     esi,2

        cmp     ax,"."
        je      .next_file
        cmp     ax,".."
        je      .next_file

        lea     edi,[.wfd]
        mov     eax,[edi+FINDDATA.dwFileAttributes]

        test    ax,FILE_ATTRIBUTE_DIRECTORY
        je      .else

        lea     edi,[.szSubPath]
        push    edi
        stdcall _zeromem,edi,MAX_PATH
        mov     edi,[esp]
        lea     eax,[.szPath]
        invoke  lstrcpy,edi,eax
        invoke  lstrlen,edi
        mov     byte [edi+eax-3],0
        invoke  lstrcat,edi,esi
        pop     edi

        inc     [iFiles]

        pushad
        stdcall _findfile,edi,[lpFileToFind],[lpBuffer]
        popad

        dec     [iFiles]
        jmp     .next_file

  .found_file:
        lea     esi,[.szPath]
        mov     edi,[lpBuffer]

        invoke  lstrlen,esi
        mov     byte [esi+eax-3],NULL

        invoke  lstrcpy,edi,esi

        lea     esi,[.wfd.cFileName]
        invoke  lstrcat,edi,esi

        mov     ecx,896 ; 844+32+20 (stack data, pushad size, params)
        mov     eax,[iFiles]
        imul    eax,ecx

        add     ebp,eax
        mov     esp,ebp

        jmp     .close_find

  .else:
        invoke  lstrcmpi,[lpFileToFind],esi
        or      eax,eax
        jz      .found_file

  .next_file:
        lea     edi,[.wfd]
        invoke  FindNextFile,[.hFind],edi
        or      eax,eax
        jg      .while_start

  .close_find:
        invoke  FindClose,[.hFind]

  .error_find:
        return
  endp

  proc  _zeromem, var,size
        invoke  RtlZeroMemory,[var],[size]
        return
  endp

section '.idata' import data readable writeable

  library       kernel32,'kernel32.dll',\
                user32,'user32.dll',\
                shell32,'shell32.dll',\
                advapi32,'advapi32.dll'

  include       '%fasminc%\apia\kernel32.inc'
  include       '%fasminc%\apia\user32.inc'
  include       '%fasminc%\apia\shell32.inc'
  include       '%fasminc%\apia\advapi32.inc'

; eof    

_________________
[not enough memory]
Post 01 Jan 2005, 13:09
View user's profile Send private message Reply with quote
beppe85



Joined: 23 Oct 2004
Posts: 181
beppe85 01 Jan 2005, 13:19
Yes, this is the real problem which precudes from a fast-return: you need to call the finalization code always.

In this case, jump into .close_find(you can invoke FindClose inline too) before return.
Post 01 Jan 2005, 13:19
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.