Джигурда со стеком

Тема в разделе "WASM.ASSEMBLER", создана пользователем Igor1024, 11 сен 2011.

  1. Igor1024

    Igor1024 Васил Троянов Боянов (Azis)

    Публикаций:
    0
    Регистрация:
    15 окт 2010
    Сообщения:
    345
    Адрес:
    Sliven, Bulgaria
    В общем, есть процедура, которая по заданной базовой директории роется в поисках .txt.
    Проблема в том, что адреса возврата иногда затираются, или же в конце концов esp указывает не на правильный адрес. Просидел пол дня с отладчиком, но так ничего наводящего на мысль не накопал.

    Кодесс:
    Код (Text):
    1. format PE
    2. include 'D:\asm\fasmw16925\INCLUDE\win32a.inc'
    3. section '.code' readable writable executable
    4.  
    5. entry start
    6. start:
    7.       mov eax,dword direct
    8.       call find_txt
    9.       invoke ExitProcess,0
    10.  
    11.  
    12. ;in -> EAX - адрес строки с директорией
    13. proc find_txt
    14.         local path db 260 dup (?);MAX_PATH
    15.         local hFile dd ?
    16.         local find WIN32_FIND_DATA
    17.  
    18.         push edi
    19.         push esi
    20.         push eax
    21.         lea edi,[path]
    22.         mov esi,eax
    23.  
    24.  .copy_strings:
    25.         cmp byte[esi],0
    26.         je .continue
    27.         mov eax,[esi]
    28.         mov [edi],eax
    29.         inc edi
    30.         inc esi
    31.         jmp .copy_strings
    32.  
    33.   .continue:
    34.         pop eax
    35.         pop esi
    36.         pop edi
    37.  
    38.         ;lea eax,[path]
    39.         ;invoke MessageBox,0,eax,mark1,0
    40.  
    41.  
    42.         pushad
    43.         lea edi,[path]
    44.         push edi
    45.         call lstrlen
    46.         dec eax
    47.         mov byte [edi+eax+1],'/'
    48.         mov byte [edi+eax+2],'*'
    49.         mov byte [edi+eax+3],0
    50.  
    51.         lea ebx,[find]
    52.         lea edi,[path]
    53.         invoke FindFirstFile,edi,ebx
    54.         cmp eax,0xFFFFFFFF
    55.         je .fail
    56.         mov [hFile],eax
    57.  
    58.  .cycle:
    59.                 push edi
    60.                 push esi
    61.                 mov edi,[hFile]
    62.                 lea edi,[edi]
    63.                 lea esi,[find]
    64.                 invoke FindNextFile,edi,esi
    65.                 pop esi
    66.                 pop edi
    67.                 test eax,eax
    68.                 jz .fail
    69.  
    70.                 ;lea eax,[path]
    71.                 ;invoke MessageBox,0,eax,mark2,0
    72.  
    73.                 lea eax,[find]
    74.                 add eax,44
    75.                 cmp word[eax],'..'
    76.                 je .cycle
    77.  
    78.  
    79.                 lea eax,[find]
    80.                 mov eax,[eax]
    81.                 and eax,FILE_ATTRIBUTE_DIRECTORY
    82.                 lea ebx,[find]
    83.                 mov ebx,[ebx]
    84.                 cmp ebx,FILE_ATTRIBUTE_DIRECTORY
    85.                 jne .got_file
    86.                 lea ecx,dword[find]
    87.                 add ecx,44; 44 - смещении имени
    88.                 cmp byte[ecx],'.'
    89.                 je .got_file
    90.  
    91.                 ;если откопали директорию
    92.                 lea edi,[path]
    93.                 push edi
    94.                 call lstrlen
    95.                 add edi,eax
    96.                 lea esi,dword [find]
    97.                 add esi,44
    98.                 push esi
    99.                 call lstrlen
    100.                 mov ecx,eax
    101.                 dec edi
    102.                 rep movsb;сливаем в путь для передачи
    103.                 mov byte[edi],'/'
    104.                 mov byte[edi+1],0
    105.  
    106.                 ;push eax
    107.                 ;lea eax,[path]
    108.                 ;invoke MessageBox,0,eax,mark3,0
    109.                 ;pop eax
    110.  
    111.                
    112.                 lea eax,[path]
    113.                 call find_txt;ок, теперь смотрим во вложенной директории
    114.                 ;и вот при возврате из вложенной функции вылетаем не туда...
    115.                 ;т.к ESP при call'е указывал на другое значение, чем после
    116. ;Если быть точнее, то на прыгаем на 0
    117.              
    118.                 ;приводим путь в нормальный вид
    119.                 lea eax,dword[find]
    120.                 add eax,44
    121.                 push eax
    122.                 call lstrlen
    123.                 sub edi,eax
    124.                 mov byte[edi],0
    125.                 jmp .cycle
    126.  
    127.  .got_file:
    128.                 lea eax,[find]
    129.                 add eax,44
    130.                 ;lea ebx,[path]
    131.                 ;push eax
    132.                 ;invoke MessageBox,0,eax,ebx,0
    133.                 ;pop eax
    134.                 mov ecx,56
    135.   .check_name:
    136.                 cmp dword [eax],'.txt'
    137.                 je .found
    138.                 cmp dword [eax],'.TXT'
    139.                 je .found
    140.                 test ecx,ecx
    141.                 jz .cycle
    142.                 inc eax
    143.                 dec ecx
    144.                 jmp .check_name
    145.   .found:
    146.                 invoke MessageBox,0,got_txt,got_txt,0
    147.                 jmp .cycle
    148.  
    149.  .fail:
    150.                 popad
    151.                 ret
    152.  
    153. endp
    154.  
    155. lstrlen:
    156.         add esp,4
    157.         pop eax
    158.         sub esp,8
    159.         push ecx
    160.         xor ecx,ecx
    161.  .cycle:
    162.         cmp byte[eax],0
    163.         je .found
    164.         inc eax
    165.         inc ecx
    166.         jmp .cycle
    167.  
    168.  .found:
    169.         mov eax,ecx
    170.         pop ecx
    171.         ret
    172.  
    173. ;Тут всякие импортируемые функции, переменные глобальные...
    174. end data
    Стековый фрейм формируется, в конце, перед ret'ом, как и положено, стоит leave, лишних push'ев я здесь не нашёл (бывает у меня так - забываю из стека забрать что-нибудь). Вот, собственно и всё.
     
  2. TrashGen

    TrashGen ТрещГен

    Публикаций:
    0
    Регистрация:
    15 мар 2011
    Сообщения:
    1.201
    Адрес:
    подполье
    Да, наверное джигурда стек портит. Бинарник выкладывайте ежеле проблема еще сохранилась.
     
  3. Igor1024

    Igor1024 Васил Троянов Боянов (Azis)

    Публикаций:
    0
    Регистрация:
    15 окт 2010
    Сообщения:
    345
    Адрес:
    Sliven, Bulgaria
    Ну здравствуй, Тришин Гена :)
    Ищет на C:\
    Что-то на васм не льёт. Сейчас на помойку скину.
    http://ifolder.ru/25677379
    ЗЫ. Зачем вам бинарь? Уже бы фасм давно стянули и скомпилили.
     
  4. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    Igor1024
    Выложите исходник, который можно будет скомпелировать.
     
  5. Igor1024

    Igor1024 Васил Троянов Боянов (Azis)

    Публикаций:
    0
    Регистрация:
    15 окт 2010
    Сообщения:
    345
    Адрес:
    Sliven, Bulgaria
    Код (Text):
    1. format PE
    2. include 'D:\asm\fasmw16925\INCLUDE\win32a.inc'
    3. section '.code' readable writable executable
    4.  
    5. entry start
    6. start:
    7.       mov eax,dword direct
    8.       call find_txt
    9.       invoke ExitProcess,0
    10.  
    11.  
    12. ;in -> EAX - адрес строки с директорией
    13. proc find_txt
    14.         local path db 260 dup (?);MAX_PATH
    15.         local hFile dd ?
    16.         local find WIN32_FIND_DATA
    17.  
    18.         push edi
    19.         push esi
    20.         push eax
    21.         lea edi,[path]
    22.         mov esi,eax
    23.  
    24.  .copy_strings:
    25.         cmp byte[esi],0
    26.         je .continue
    27.         mov eax,[esi]
    28.         mov [edi],eax
    29.         inc edi
    30.         inc esi
    31.         jmp .copy_strings
    32.  
    33.   .continue:
    34.         pop eax
    35.         pop esi
    36.         pop edi
    37.  
    38.         ;lea eax,[path]
    39.         ;invoke MessageBox,0,eax,mark1,0
    40.  
    41.  
    42.         pushad
    43.         lea edi,[path]
    44.         push edi
    45.         call lstrlen
    46.         dec eax
    47.         mov byte [edi+eax+1],'/'
    48.         mov byte [edi+eax+2],'*'
    49.         mov byte [edi+eax+3],0
    50.  
    51.         lea ebx,[find]
    52.         lea edi,[path]
    53.         invoke FindFirstFile,edi,ebx
    54.         cmp eax,0xFFFFFFFF
    55.         je .fail
    56.         mov [hFile],eax
    57.  
    58.  .cycle:
    59.                 push edi
    60.                 push esi
    61.                 mov edi,[hFile]
    62.                 lea edi,[edi]
    63.                 lea esi,[find]
    64.                 invoke FindNextFile,edi,esi
    65.                 pop esi
    66.                 pop edi
    67.                 test eax,eax
    68.                 jz .fail
    69.  
    70.                 ;lea eax,[path]
    71.                 ;invoke MessageBox,0,eax,mark2,0
    72.  
    73.                 lea eax,[find]
    74.                 add eax,44
    75.                 cmp word[eax],'..'
    76.                 je .cycle
    77.  
    78.  
    79.                 lea eax,[find]
    80.                 mov eax,[eax]
    81.                 and eax,FILE_ATTRIBUTE_DIRECTORY
    82.                 lea ebx,[find]
    83.                 mov ebx,[ebx]
    84.                 cmp ebx,FILE_ATTRIBUTE_DIRECTORY
    85.                 jne .got_file
    86.                 lea ecx,dword[find]
    87.                 add ecx,44; 44 - смещении имени
    88.                 cmp byte[ecx],'.'
    89.                 je .got_file
    90.  
    91.                 ;если откопали директорию
    92.                 lea edi,[path]
    93.                 push edi
    94.                 call lstrlen
    95.                 add edi,eax
    96.                 lea esi,dword [find]
    97.                 add esi,44
    98.                 push esi
    99.                 call lstrlen
    100.                 mov ecx,eax
    101.                 dec edi
    102.                 rep movsb;сливаем в путь для передачи
    103.                 mov byte[edi],'/'
    104.                 mov byte[edi+1],0
    105.  
    106.                 ;push eax
    107.                 ;lea eax,[path]
    108.                 ;invoke MessageBox,0,eax,mark3,0
    109.                 ;pop eax
    110.  
    111.                
    112.                 lea eax,[path]
    113.                 call find_txt;ок, теперь смотрим во вложенной директории
    114.                 ;и вот при возврате из вложенной функции вылетаем не туда...
    115.                 ;т.к ESP при call'е указывал на другое значение, чем после
    116. ;Если быть точнее, то на прыгаем на 0
    117.              
    118.                 ;приводим путь в нормальный вид
    119.                 lea eax,dword[find]
    120.                 add eax,44
    121.                 push eax
    122.                 call lstrlen
    123.                 sub edi,eax
    124.                 mov byte[edi],0
    125.                 jmp .cycle
    126.  
    127.  .got_file:
    128.                 lea eax,[find]
    129.                 add eax,44
    130.                 ;lea ebx,[path]
    131.                 ;push eax
    132.                 ;invoke MessageBox,0,eax,ebx,0
    133.                 ;pop eax
    134.                 mov ecx,56
    135.   .check_name:
    136.                 cmp dword [eax],'.txt'
    137.                 je .found
    138.                 cmp dword [eax],'.TXT'
    139.                 je .found
    140.                 test ecx,ecx
    141.                 jz .cycle
    142.                 inc eax
    143.                 dec ecx
    144.                 jmp .check_name
    145.   .found:
    146.                 invoke MessageBox,0,got_txt,got_txt,0
    147.                 jmp .cycle
    148.  
    149.  .fail:
    150.                 popad
    151.                 ret
    152.  
    153. endp
    154.  
    155. lstrlen:
    156.         add esp,4
    157.         pop eax
    158.         sub esp,8
    159.         push ecx
    160.         xor ecx,ecx
    161.  .cycle:
    162.         cmp byte[eax],0
    163.         je .found
    164.         inc eax
    165.         inc ecx
    166.         jmp .cycle
    167.  
    168.  .found:
    169.         mov eax,ecx
    170.         pop ecx
    171.         ret
    172.  
    173. section '.data' readable writable
    174. direct db 'C:/',0
    175. got_txt db 'Got it',0
    176. mark1 db 'mark1',0; для отладки
    177. mark2 db 'mark2',0
    178. mark3 db 'mark3',0
    179.  
    180. section '.import' readable writable
    181. data import
    182. library kernel32,'KERNEL32.DLL'\
    183.            user32,'USER32.DLL'
    184. import kernel32,\
    185. ExitProcess,'ExitProcess',\
    186. FindFirstFile,'FindFirstFileA',\
    187. FindNextFile,'FindNextFileA'
    188.  
    189. import user32,\
    190. MessageBox,'MessageBoxA'
    191. end data
     
  6. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    Должно быть копирование по одному байту, а не по четыре.
    Слеши, кстати ставить обратные: не / а \.
    Не поможет в случае ".TxT". Для таких случаев есть lstrcmpi.
    Вот рабочий код:
    Код (Text):
    1. format  PE CONSOLE 5.0
    2. include "win32wxp.inc"
    3. entry   start
    4.  
    5. section ".text" code readable executable
    6.  
    7.   dir_name      TCHAR "C:\", 0
    8.   asterisk      TCHAR "*", 0
    9.   txt_extension TCHAR ".txt", 0
    10.   line_feed     TCHAR 10
    11. start:
    12.         stdcall       find_txt, dir_name
    13.         invoke        Sleep, -1
    14.         invoke        ExitProcess, 0
    15.  
    16. proc    find_txt uses ebx esi edi, dir_name
    17.  
    18.         local   wfd:WIN32_FIND_DATA
    19.         local   search_mask[MAX_PATH]:TCHAR
    20.         local   file_name[MAX_PATH]:TCHAR
    21.  
    22.         lea     esi, [search_mask]
    23.         lea     edi, [file_name]
    24.         invoke  lstrcpy, esi, [dir_name]
    25.         invoke  PathCombine, esi, esi, asterisk
    26.         invoke  FindFirstFile, esi, addr wfd
    27.         cmp     eax, INVALID_HANDLE_VALUE
    28.         je      .end_search
    29.         mov     ebx, eax
    30.   .do_search:
    31.         invoke  PathCombine, edi, [dir_name], addr wfd.cFileName
    32.         test    [wfd.dwFileAttributes], FILE_ATTRIBUTE_DIRECTORY
    33.         jnz     .dir_found
    34.   .file_found:
    35.         invoke  PathFindExtension, edi
    36.         invoke  lstrcmpi, eax, txt_extension
    37.         test    eax, eax
    38.         jnz     .continue_search
    39.   .txt_file_found:
    40.         invoke  WriteConsole, <invoke GetStdHandle, STD_OUTPUT_HANDLE>, edi, <invoke lstrlen, edi>, NULL, NULL
    41.         invoke  WriteConsole, <invoke GetStdHandle, STD_OUTPUT_HANDLE>, line_feed, 1, NULL, NULL
    42.         jmp     .continue_search
    43.   .dir_found:
    44.         cmp     [wfd.cFileName], '.'    ; skip . and ..
    45.         je      .continue_search
    46.         stdcall find_txt, edi
    47.   .continue_search:
    48.         invoke  FindNextFile, ebx, addr wfd
    49.         test    eax, eax
    50.         jnz     .do_search
    51.   .end_search:
    52.         ret
    53.  
    54. endp
    55.  
    56.  
    57.  
    58.  
    59. section ".idata" import data readable writeable
    60.  
    61.   library kernel32, "kernel32.dll", \
    62.           shlwapi, "shlwapi.dll"
    63.  
    64.   include "api\kernel32.inc"
    65.   import  shlwapi, \
    66.           PathCombineA, "PathCombineA", \
    67.           PathCombineW, "PathCombineW", \
    68.           PathFindExtensionA, "PathFindExtensionA", \
    69.           PathFindExtensionW, "PathFindExtensionW"
    70.  
    71.   api PathCombine, \
    72.       PathFindExtension
     
  7. h0t

    h0t Member

    Публикаций:
    0
    Регистрация:
    3 апр 2011
    Сообщения:
    735
    Код (Text):
    1. lstrlen:
    2.         add esp,4
    3.         pop eax
    4.         sub esp,8
    5.         push ecx
    6.         xor ecx,ecx
    7.  .cycle:
    8.         cmp byte[eax],0
    9.         je .found
    10.         inc eax
    11.         inc ecx
    12.         jmp .cycle
    13.  
    14.  .found:
    15.         mov eax,ecx
    16.         pop ecx
    17.         ret
    А кто будет восстанавливать стек?
    Виновата именно эта функция
     
  8. Igor1024

    Igor1024 Васил Троянов Боянов (Azis)

    Публикаций:
    0
    Регистрация:
    15 окт 2010
    Сообщения:
    345
    Адрес:
    Sliven, Bulgaria
    Ezrah, слеши не менял, всё равно работает. Ищет то хорошо, проблема в стеке.
    Да, с копированием я тупанул. Исправил. (Хотя, в принципе, результат одинаков).
    h0t, что то не допёр. Если вы про стековый фрейм, то в начале

    Код (Text):
    1. push ebp       ;
    2. mov ebp,esp  ; enter
    3. sub esp,554   ;
    а в конце

    Код (Text):
    1. popad          
    2. mov esp,ebp ;leave
    3. pop ebp        ;
    4. ret
    Так что про какое восстановление стека Вы говорите? Стек после локальных переменных восстанавливаем, вроде бы лишних push'ев нет.
     
  9. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    В lstrlen должно быть retn 4.
     
  10. Igor1024

    Igor1024 Васил Троянов Боянов (Azis)

    Публикаций:
    0
    Регистрация:
    15 окт 2010
    Сообщения:
    345
    Адрес:
    Sliven, Bulgaria
    h0t,Ezrah, да, была у меня такая мысль... Но что-то на неё я не особо посмотрел. А слона то я и не заметил ;) Спасибо.
    Вот отредактированный на свежую голову вариант (может кому-нибудь понадобится):

    Код (Text):
    1. format PE
    2. include 'D:\asm\fasmw16925\INCLUDE\win32a.inc'
    3. section '.code' readable writable executable
    4.  
    5. entry start
    6. start:
    7.       mov eax,dword direct
    8.       call find_txt
    9.       invoke ExitProcess,0
    10.  
    11.  
    12. ;__fastcall find_txt(DWORD Dir)
    13. proc find_txt
    14.         local path dd 260 dup (?);MAX_PATH
    15.         local hFile dd ?
    16.         local find WIN32_FIND_DATA
    17.  
    18.         push edi
    19.         push esi
    20.         push eax
    21.         lea edi,[path]
    22.         mov esi,eax
    23.  
    24.  .copy_strings:
    25.         cmp byte[esi],0
    26.         je .continue
    27.         mov al,byte[esi]
    28.         mov [edi],al
    29.         inc edi
    30.         inc esi
    31.         jmp .copy_strings
    32.  
    33.   .continue:
    34.         mov byte[edi],0
    35.         lea edi,[path]
    36.         invoke MessageBox,0,edi,edi,0
    37.         pop eax
    38.         pop esi
    39.         pop edi
    40.  
    41.         pushad
    42.         lea edi,[path]
    43.         push edi
    44.         call lstrlen
    45.         dec eax
    46.         mov byte [edi+eax+1],'/'
    47.         mov byte [edi+eax+2],'*'
    48.         mov byte [edi+eax+3],0
    49.  
    50.         lea ebx,[find]
    51.         lea edi,[path]
    52.         invoke FindFirstFile,edi,ebx
    53.         cmp eax,0xFFFFFFFF
    54.         je .fail
    55.         mov [hFile],eax
    56.  
    57.  .cycle:
    58.                 push edi
    59.                 push esi
    60.                 mov edi,[hFile]
    61.                 lea edi,[edi]
    62.                 lea esi,[find]
    63.                 invoke FindNextFile,edi,esi
    64.                 pop esi
    65.                 pop edi
    66.                 test eax,eax
    67.                 jz .fail
    68.  
    69.                 lea eax,[find]
    70.                 add eax,44
    71.                 cmp word[eax],'..'
    72.                 je .cycle
    73.  
    74.  
    75.                 lea eax,[find]
    76.                 mov eax,[eax]
    77.                 and eax,FILE_ATTRIBUTE_DIRECTORY
    78.                 cmp eax,FILE_ATTRIBUTE_DIRECTORY
    79.                 jne .got_file
    80.                 lea ecx,dword[find]
    81.                 add ecx,44
    82.                 cmp byte[ecx],'.'
    83.                 je .got_file
    84.  
    85.                 lea edi,[path]
    86.                 push edi
    87.                 call lstrlen
    88.                 add edi,eax
    89.                 lea esi,dword [find]
    90.                 add esi,44
    91.                 push esi
    92.                 call lstrlen
    93.                 mov ecx,eax
    94.                 dec edi
    95.                 rep movsb
    96.                 mov byte[edi],'/'
    97.                 mov byte[edi+1],0
    98.  
    99.                
    100.                 lea eax,[path]
    101.                 call find_txt
    102.                
    103.                 lea eax,dword[find]
    104.                 add eax,44
    105.                 push eax
    106.                 call lstrlen
    107.                 sub edi,eax
    108.                 mov byte[edi],0
    109.                 jmp .cycle
    110.  
    111.  .got_file:
    112.                 lea eax,[find]
    113.                 add eax,44
    114.                 lea ebx,[path]
    115.                 lea ecx,[find]
    116.                 add ecx,44
    117.                 push eax
    118.                 push ecx
    119.                 call lstrlen
    120.                 mov ecx,eax
    121.                 pop eax
    122.   .check_name:
    123.                 cmp dword [eax],'.txt'
    124.                 je .found
    125.                 cmp dword [eax],'.TXT'
    126.                 je .found
    127.                 test ecx,ecx
    128.                 jz .cycle
    129.                 inc eax
    130.                 dec ecx
    131.                 jmp .check_name
    132.   .found:
    133.                 invoke MessageBox,0,got_txt,got_txt,0
    134.                 lea edi,[path]
    135.                 lea esi,[find]
    136.                 add esi,44
    137.                 invoke MessageBox,0,edi,esi,0
    138.                 jmp .cycle
    139.  
    140.  .fail:
    141.                 popad
    142.                 ret
    143.  
    144. endp
    145.  
    146.  
    147. lstrlen:
    148.         add esp,4
    149.         pop eax
    150.         sub esp,8
    151.         push ecx
    152.         xor ecx,ecx
    153.  .cycle:
    154.         cmp byte[eax],0
    155.         je .found
    156.         inc eax
    157.         inc ecx
    158.         jmp .cycle
    159.  
    160.  .found:
    161.         mov eax,ecx
    162.         pop ecx
    163.         retn 4
    164.  
    165. section '.data' readable writable
    166. direct       db 'D:/',0
    167. db 100 dup (0)
    168. got_txt      db 'We got it',0
    169.  
    170.  
    171. section '.import' readable writable
    172.  
    173. data import
    174.  library kernel32,'KERNEL32.DLL',\
    175.          user32,'USER32.DLL'
    176.  
    177.  import  kernel32,\
    178.         ExitProcess,'ExitProcess',\
    179.         FindFirstFile,'FindFirstFileA',\
    180.         FindNextFile,'FindNextFileA',\
    181.         HeapAlloc,'HeapAlloc'
    182.  
    183.  import user32,\
    184.         MessageBox,'MessageBoxA'
    185.  
    186. end data