Делаю свой текстовый редактор и столкнулся с такой проблемой: Code (Text): proc WindowProc hwnd,wmsg,wparam,lparam push ebx esi edi cmp [wmsg],WM_CREATE je .wmcreate cmp [wmsg],WM_SETFOCUS je .wmsetfocus cmp [wmsg],WM_COMMAND je .wmcommand cmp [wmsg],WM_CLOSE je .wmclose cmp [wmsg],WM_DESTROY je .wmdestroy .defwndproc: invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp .finish .wmcreate: invoke GetClientRect,[hwnd],client invoke CreateWindowEx,WS_EX_CLIENTEDGE,cEdit,0,WS_VISIBLE+WS_CHILD+ES_MULTILINE+WS_HSCROLL+WS_VSCROLL+ES_AUTOHSCROLL+ES_AUTOVSCROLL,[client.left],[client.top],[client.right],[client.bottom],[hwnd],1000,[wc.hInstance],0 cmp eax,0 je .failed mov [hEdit],eax invoke SendMessage,[hEdit],EM_LIMITTEXT,MEMSIZE-1,0 invoke CreateFont,16,0,0,0,0,FALSE,FALSE,FALSE,RUSSIAN_CHARSET,OUT_RASTER_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH+FF_DONTCARE,fontname cmp eax,0 je .failed invoke SendMessage,[hEdit],WM_SETFONT,eax,TRUE xor eax,eax jmp .finish .failed: mov eax,-1 jmp .finish .wmsetfocus: invoke SetFocus,[hEdit] xor eax,eax jmp .finish .wmclose: jmp .finish .wmcommand: mov eax,[wparam] cmp ax,IDM_NEW je .NEW ; Menu 'Edit' cmp ax,IDM_UNDO je .UNDO cmp ax,IDM_CUT je .CUT cmp ax,IDM_COPY je .COPY cmp ax,IDM_PASTE je .PASTE jmp .finish .NEW: invoke SendMessage,[hEdit],EM_GETMODIFY,0,0 cmp eax,0 je clear invoke MessageBox,[hwnd],savefileq,qtitle,MB_YESNOCANCEL cmp eax,IDYES je save_file cmp eax,IDNO je close cmp eax,IDCANCEL je finish clear: invoke SendMessage,[hEdit],WM_SETTEXT,0,0 save_file: mov [ofn.Flags],OFN_EXPLORER+OFN_OVERWRITEPROMPT invoke GetSaveFileName,ofn cmp eax,0 je .finish invoke CreateFile,filename,GENERIC_READ+GENERIC_WRITE,FILE_SHARE_READ+FILE_SHARE_WRITE,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0 mov [hFile],eax invoke GetProcessHeap mov [hHeap],eax invoke HeapAlloc,[hHeap],HEAP_ZERO_MEMORY,MEMSIZE mov [pMem],eax invoke SendMessage,[hEdit],WM_GETTEXT,MEMSIZE,[pMem] invoke lstrlen,[pMem] invoke WriteFile,[hFile],[pMem],eax,sBuf,0 mov [filesaved],1 invoke SendMessage,[hEdit],EM_SETMODIFY,0,0 invoke HeapFree,[hHeap],0,[pMem] invoke CloseHandle,[hFile] close: invoke ExitProcess,0 finish: ret jmp .finish .UNDO: invoke SendMessage,[hEdit],EM_UNDO,0,0 jmp .finish .CUT: invoke SendMessage,[hEdit],WM_CUT,0,0 jmp .finish .COPY: invoke SendMessage,[hEdit],WM_COPY,0,0 jmp .finish .PASTE: invoke SendMessage,[hEdit],WM_PASTE,0,0 jmp .finish .wmdestroy: invoke PostQuitMessage,0 xor eax,eax .finish: pop edi esi ebx ret endp при компиляции выдает сообщение: undefined symbol в строках: cmp [wmsg],WM_DESTROY je .wmdestroy <-----вот тут Получается что он не видит .wmdestroy хотя он есть. как правильнее организовать код?
может быть можно вынести save_file в отдельную процедуру, чтобы я потом мог cmp eax,0 call save_file просто я не знаю пока точно как работать с cmp и как можно вызвать проуедуру после сравнения
начинать метку с точки или другого символа-разделителя верный путь получить грабли оставте точку для полей стуктур
DuXeN0N 1) Лучше cmp eax,0 заменить на test eax,eax и быстрее и байт меньше занимает 2) процедура начинается с push ebx,esi,edi и заканчивается pop edi, esi, ebx хотя в самой процедуре edi, esi, ebx не используются 3) invoke SendMessage,[hEdit],WM_SETFONT,eax,TRUE / xor eax,eax invoke SetFocus,[hEdit]/ xor eax,eax invoke PostQuitMessage,0 / xor eax,eax попробуйте закоментировать xor eax,eax программа от этого хуже работать не будет 4) вместо invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] / jmp .finish поставте просто jmp DefWindowProc дело в том, что WindowProc имеет теже самые параметры что и DefWindowProc а про оптимизацию почитайте Сам себе Iczelion
спасибо огромное! Mikl___: вот это заменил: Code (Text): invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp finish на jmp DefWindowProc и программа вылетает при запуске. убрал push ebx,esi,edi и pop. а почему в обычном шаблоне у FASM (называется Template) там есть proc WindowProc uses ebx esi edi hwnd,wmsg,wparam,lparam или что то вроде этого. и еще хотел спросить-чем отличается ret от retn?
Метки с точкои (.wmdestroy) принадлежат к меткам без точек(WindowProc). Тоесть ты можешь написать "je WindowProc.wmdestroy." Но у тебя в коде есть метка "save_file:" а потом и "finish:". Они перекрывают WindowProc и тебе надо писать "je finish.wmdestroy". Лучше разнести весь код по разным процедурам
ret - 1 байт, retn - 2 байта. retn рекомендуется использовать для увеличения скорости если процедура вызывается часто. Самое главное что у retn есть дополнительний операнд. Можно написат "retn 0" или "retn 16". Число будет добавлено к esp
огромное спасибо. и еще 2 вопроса. в чем разница между call и stdcall и как после сравнения вызвать процедуру? например test eax,eax jz rprp proc rprp /// endp так? как ее можно вызвать? если например eax=0 то одна, если 1 то другая
DuXeN0N, в макросе proc фасма ret – это макрос, который убирает за собой мусор (восстанавливает регистры, стековый кадр и т. п., и в конце делает retn x, причём сколько x будет, вычисляет сам), retn же – обычная ассемблерная инструкция. Повторюсь, разница только внутри proc. Вне proc между retn и ret разницы нет. Двухбайтовый вариант генерируется с аргументом (retn 0x20 или ret 4, например), без аргумента (retn или ret) – однобайтовый.
Что за бред? ret это макрос, результат которого подставит компилятор в зависимости от типа процедуры (near, far) и в зависимости от того, нужно или нет убирать параметры переданные процедуре код команды retn без параметров 0C3h - длина 1 байт код retn XX -- 0С2h XX - длина 3 байта код retf без параметров -- 0CBh - длина 1 байт код retf XX -- 0CAh XX - длина 3 байта
Mikl___, Code (Text): cmp eax,IDYES je save_file cmp eax,IDNO je close cmp eax,IDCANCEL je nothing это можно упростить как-нибудь?
напиши код в VC - он сам тебе соптимизирует и test eax, eax и все джампы. вообще писать гую на асме занятие неблагодарное. switch - case и работать будет быстрее чем cmp, je (в некоторых случаях), и код будет читаемей.
я уже упростил. убрал третье сравнение получилось так: Code (Text): cmp eax,IDNO je clear cmp eax,IDCANCEL je finish call SaveFile jmp finish
У меня профессиональный интерес -- во что, кроме cmp/je превращается switch - case в VC и за счет чего он будет быстрее работать? Приведите пример, пожалуйста, заодно сравните с вариантами switch - case в Сам себе Iczelion Просто очень интересно...