ESI EDI и WinAPI

Тема в разделе "WASM.WIN32", создана пользователем Assasin291, 21 сен 2011.

  1. Assasin291

    Assasin291 New Member

    Публикаций:
    0
    Регистрация:
    15 сен 2011
    Сообщения:
    8
    В программе есть 3 диалога и менюшка. В 1-м диалоге вводится строка, в которой нужно выделить слова, а затем вывести их в клиентскую область столбиком. Для вывода я использую сообщение WM_PAINT, в нём вызываю свою функцию, которая отвечает за вывод строки. Проблема с сохранением esi edi. Из-за того что я не могу их сохранить, не вызываются WinAPI функции.(вызов диалогов, например)

    Код (Text):
    1. OutProc proc uses ebx edi esi hdc:HDC           ;hDC передаётся из WM_PAINT (функция - WndProc)
    2.         xor eax,eax
    3.         invoke lstrlen,addr szStr                   ;нахожу длину строки
    4.         cmp eax,0                               ;если длина строки равна 0, то заканчиваю выполнение
    5.         je @End
    6.         mov ecx,eax                         ;иначе делаю счётчик равным длине строки + 2
    7.         add ecx,2
    8.         mov al,' '
    9.         mov szStr[ecx],al                       ;добавляю в конец строки пробел, чтобы не пропустить последнее слово в строке
    10.         mov pt.x,20
    11.         mov pt.y,20                         ;координаты для TextOut
    12.  
    13.     push edi
    14.     push esi
    15.  
    16.         mov esi,offset szStr                        ;не получается сохранить esi edi
    17.         mov edi,offset szBuf
    18.  
    19.     mov tmp_s,esi                               ;сохраняю адрес символа, на котором остановился
    20.  
    21.         xor ebx,ebx
    22. @Prepare:
    23.     mov esi,tmp_s                               ;восстанавливаю адрес символа
    24.  
    25.         mov al,' '                              ;при вызове WinAPI функций (они находятся ниже) eax портится, поэтому заношу ' ' в al
    26.         cmp al,[esi]                            ;сравниваю с символом в source строке
    27.         jne @Skip                               ;если символ строки не ' ', то перехожу к алгоритму копирования слова в другую строку (edi)
    28.         inc esi                             ;увеличиваю esi (перехожу к следующему символу)
    29.         loop @Prepare
    30. @Skip:
    31.         cmp al,[esi]                            ;опять сравниваю с пробелом. (если наткнулся на него, значит в edi занесено всё слово)
    32.         je @Paint                               ;если нахожу ' ', то приступаю к его выводу
    33.         movsb
    34.         loop @Skip
    35. @Paint:
    36.         xor al,al
    37.         mov [edi],al                            ;добавляю к концу строки ноль, чтобы не выводило лишнего
    38.  
    39.     mov tmp_s,esi                               ;сохраняю в переменную адрес символа, на котором остановился
    40.     pop esi                                 ;перед вызовом API функций восстанавливаю значения esi edi
    41.     pop edi
    42.  
    43.         push ecx                                ;сохраняю регистры, т. к. WinAPI функции могут их испортить
    44.         push ebx
    45.         invoke SetTextColor,hdc,cstclr[ebx]
    46.         invoke lstrlen,addr szBuf
    47.         invoke TextOut,hdc,pt.x,pt.y,addr szBuf,eax
    48.         pop ebx                             ;восстанавливаю ebx (он отвечает за цвет выведенного слова)
    49.         add bl,4
    50.         cmp bl,64
    51.         jne @Z
    52.         xor bl,bl
    53. @Z:
    54.         pop ecx                             ;восстанавливаю счётчик
    55.  
    56.     push edi                                    ;сохраняю значения esi edi после вызова API функций
    57.     push esi
    58.  
    59.         add pt.y,20                         ;следующее слово будет смещено на 20 пикселей вниз
    60.         mov edi,offset szBuf                        ;edi указывает на начало строки szBuf
    61.  
    62.     dec ecx                                 ;т. к. метка @Prepare слишком далеко (пока), за переход отвечают эти 3 команды
    63.     cmp ecx,0
    64.     jne @Prepare
    65.         ;loop @Prepare
    66.  
    67. @End:
    68.     ret
    69. OutProc endp
    Навсякий кидаю весь проект.
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Функции API не изменяют регистры ebx, edi, esi. Поэтому достаточно одного uses в заголовке процедуры, а многочисленные пуши\попы этих регистров не имеют смысла и только запутывают код и приводят к ошибкам.
    В частности из-за дурного\ненужного mov esi,tmp_s в начале @Prepare у тебя этот первый loop @Prepare работает не правильно, т.к. если tmp_s указывает на пробел, то jne @Skip никогда не срабатывает и loop прокручивает все символы строки, а вслед за этим и цикл loop @Skip работает не правильно, копируя только один символ, т.к. ecx уже = 0
     
  3. Assasin291

    Assasin291 New Member

    Публикаций:
    0
    Регистрация:
    15 сен 2011
    Сообщения:
    8
    Я сначала так и делал (у меня был только uses в заголовке процедуры, без push и прочего бреда), но если выбрать в меню пункт "Text", ввести что-либо и нажать OK, то перестают работать вызовы диалогов (сообщения обрабатываются). Проблема именно в том, что я выполняю команды
    Код (Text):
    1. mov esi,offset szStr
    2. mov edi,offset szBuf
    Если вместо esi,edi использовать другие регистры, то такой проблемы нет.
     
  4. valentin_p

    valentin_p New Member

    Публикаций:
    0
    Регистрация:
    11 фев 2011
    Сообщения:
    382
    меняет есессна eax, и ecx edx, esp(lol)
    покажите бинарник, с int3 перед апи той
     
  5. Assasin291

    Assasin291 New Member

    Публикаций:
    0
    Регистрация:
    15 сен 2011
    Сообщения:
    8
    Извиняюсь... Я был неправ. Проблема, похоже, была в самом алгоритме. Исправил.
    P. S. Спасибо всем.