В программе есть 3 диалога и менюшка. В 1-м диалоге вводится строка, в которой нужно выделить слова, а затем вывести их в клиентскую область столбиком. Для вывода я использую сообщение WM_PAINT, в нём вызываю свою функцию, которая отвечает за вывод строки. Проблема с сохранением esi edi. Из-за того что я не могу их сохранить, не вызываются WinAPI функции.(вызов диалогов, например) Код (Text): OutProc proc uses ebx edi esi hdc:HDC ;hDC передаётся из WM_PAINT (функция - WndProc) xor eax,eax invoke lstrlen,addr szStr ;нахожу длину строки cmp eax,0 ;если длина строки равна 0, то заканчиваю выполнение je @End mov ecx,eax ;иначе делаю счётчик равным длине строки + 2 add ecx,2 mov al,' ' mov szStr[ecx],al ;добавляю в конец строки пробел, чтобы не пропустить последнее слово в строке mov pt.x,20 mov pt.y,20 ;координаты для TextOut push edi push esi mov esi,offset szStr ;не получается сохранить esi edi mov edi,offset szBuf mov tmp_s,esi ;сохраняю адрес символа, на котором остановился xor ebx,ebx @Prepare: mov esi,tmp_s ;восстанавливаю адрес символа mov al,' ' ;при вызове WinAPI функций (они находятся ниже) eax портится, поэтому заношу ' ' в al cmp al,[esi] ;сравниваю с символом в source строке jne @Skip ;если символ строки не ' ', то перехожу к алгоритму копирования слова в другую строку (edi) inc esi ;увеличиваю esi (перехожу к следующему символу) loop @Prepare @Skip: cmp al,[esi] ;опять сравниваю с пробелом. (если наткнулся на него, значит в edi занесено всё слово) je @Paint ;если нахожу ' ', то приступаю к его выводу movsb loop @Skip @Paint: xor al,al mov [edi],al ;добавляю к концу строки ноль, чтобы не выводило лишнего mov tmp_s,esi ;сохраняю в переменную адрес символа, на котором остановился pop esi ;перед вызовом API функций восстанавливаю значения esi edi pop edi push ecx ;сохраняю регистры, т. к. WinAPI функции могут их испортить push ebx invoke SetTextColor,hdc,cstclr[ebx] invoke lstrlen,addr szBuf invoke TextOut,hdc,pt.x,pt.y,addr szBuf,eax pop ebx ;восстанавливаю ebx (он отвечает за цвет выведенного слова) add bl,4 cmp bl,64 jne @Z xor bl,bl @Z: pop ecx ;восстанавливаю счётчик push edi ;сохраняю значения esi edi после вызова API функций push esi add pt.y,20 ;следующее слово будет смещено на 20 пикселей вниз mov edi,offset szBuf ;edi указывает на начало строки szBuf dec ecx ;т. к. метка @Prepare слишком далеко (пока), за переход отвечают эти 3 команды cmp ecx,0 jne @Prepare ;loop @Prepare @End: ret OutProc endp Навсякий кидаю весь проект.
Функции API не изменяют регистры ebx, edi, esi. Поэтому достаточно одного uses в заголовке процедуры, а многочисленные пуши\попы этих регистров не имеют смысла и только запутывают код и приводят к ошибкам. В частности из-за дурного\ненужного mov esi,tmp_s в начале @Prepare у тебя этот первый loop @Prepare работает не правильно, т.к. если tmp_s указывает на пробел, то jne @Skip никогда не срабатывает и loop прокручивает все символы строки, а вслед за этим и цикл loop @Skip работает не правильно, копируя только один символ, т.к. ecx уже = 0
Я сначала так и делал (у меня был только uses в заголовке процедуры, без push и прочего бреда), но если выбрать в меню пункт "Text", ввести что-либо и нажать OK, то перестают работать вызовы диалогов (сообщения обрабатываются). Проблема именно в том, что я выполняю команды Код (Text): mov esi,offset szStr mov edi,offset szBuf Если вместо esi,edi использовать другие регистры, то такой проблемы нет.