написал прогу (см. ниже), компиляция проходит успешно, но при запуске появляется консоль и сообщение об ощибке. Помогите разобраться в чём тут дело, также хотелось бы узнать как улучшить листинг. заранее спасибо! Код (Text): .386 .model flat,stdcall option casemap:none include \masm32\include\kernel32.inc include \masm32\include\user32.inc include \masm32\include\windows.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib .data ClassName db "MyClass",0 AppName db "MyApp",0 .data? hInstance HINSTANCE ? CommandLine LPSTR ? .code start: push NULL call GetModuleHandle mov hInstance,eax call GetCommandLine mov CommandLine,eax call windowmain push eax call ExitProcess windowmain proc hInst:HINSTANCE,pInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL msg:MSG LOCAL hwnd:HWND LOCAL window:WNDCLASSEX mov window.cbSize,SIZEOF WNDCLASSEX mov window.style,CS_HREDRAW or CS_VREDRAW mov window.lpfnWndProc,offset WindowMessageProcessingProcedure push IDC_ARROW push NULL call LoadCursor mov window.hCursor,eax push IDI_APPLICATION push NULL call LoadIcon mov window.hIcon,eax mov window.hIconSm,eax mov window.cbClsExtra,NULL mov window.cbWndExtra,NULL push hInstance pop window.hInstance mov window.hbrBackground,COLOR_WINDOW+1 mov window.lpszMenuName,NULL mov window.lpszClassName,OFFSET ClassName push [window] call RegisterClassEx push offset ClassName push offset AppName push WS_OVERLAPPEDWINDOW push CW_USEDEFAULT push CW_USEDEFAULT push CW_USEDEFAULT push CW_USEDEFAULT push NULL push NULL push hInst push NULL call CreateWindowEx mov hwnd,eax push CmdShow push hwnd call ShowWindow push hwnd call UpdateWindow .WHILE TRUE push 0 push 0 push NULL push msg call GetMessage .BREAK .IF(!eax) push msg call TranslateMessage push msg call DispatchMessage .ENDW mov eax,msg.wParam ret windowmain endp WindowMessageProcessingProcedure proc hwnd:HWND,umsg:UINT,wpar:WPARAM,lpar:LPARAM .IF umsg==WM_DESTROY push NULL call PostQuitMessage .ENDIF xor eax,eax ret WindowMessageProcessingProcedure endp end start
1. Отладчика не существует? Скомпилируй и прогони под Олли-дебагером. Найди ошибку. Или ты хочешь, чтобы мы за тебя отлавливали баги? 2. Читай правила форума о названиях тем
Ты написал: Код (Text): windowmain proc hInst:HINSTANCE,pInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD Но вызвал: Код (Text): call windowmain В результате вот тут: Код (Text): ... push hInst ... push CmdShow ... в стек заносится (пытается занести!) неизвестно чего... а вот тут: Код (Text): ... ret windowmain endp при возврате происходит (если не вылетит с ошибкой раньше) чистка стека от параметров процедуры, которые никто туда не помещал...
На первый взгляд ошибка тут В твою функцию, согласно прототипу, передается 4 аргумента Значит на выходе функции из стека вытолкнется 12 байт. Однако ты вызываешь свою функцию не передав ей НИ ОДНОГО аргумента, тем самым портишь стек и натыкаешься на ошибку
теперь передал (вроде ) но не помогает всё также Код (Text): .386 .model flat,stdcall option casemap:none include \masm32\include\kernel32.inc include \masm32\include\user32.inc include \masm32\include\windows.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib .data ClassName db "MyClass",0 AppName db "MyApp",0 .data? hInstance HINSTANCE ? CommandLine LPSTR ? .code start: push NULL call GetModuleHandle mov hInstance,eax call GetCommandLine mov CommandLine,eax push NULL push CommandLine push NULL push hInstance call windowmain push eax call ExitProcess windowmain proc hInst:HINSTANCE,pInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL msg:MSG LOCAL hwnd:HWND LOCAL window:WNDCLASSEX mov window.cbSize,SIZEOF WNDCLASSEX mov window.style,CS_HREDRAW or CS_VREDRAW mov window.lpfnWndProc,offset WindowMessageProcessingProcedure push IDC_ARROW push NULL call LoadCursor mov window.hCursor,eax push IDI_APPLICATION push NULL call LoadIcon mov window.hIcon,eax mov window.hIconSm,eax mov window.cbClsExtra,NULL mov window.cbWndExtra,NULL push hInstance pop window.hInstance mov window.hbrBackground,COLOR_WINDOW+1 mov window.lpszMenuName,NULL mov window.lpszClassName,OFFSET ClassName push [window] call RegisterClassEx push offset ClassName push offset AppName push WS_OVERLAPPEDWINDOW push CW_USEDEFAULT push CW_USEDEFAULT push CW_USEDEFAULT push CW_USEDEFAULT push NULL push NULL push hInst push NULL call CreateWindowEx mov hwnd,eax push CmdShow push hwnd call ShowWindow push hwnd call UpdateWindow .WHILE TRUE push 0 push 0 push NULL push msg call GetMessage .BREAK .IF(!eax) push msg call TranslateMessage push msg call DispatchMessage .ENDW mov eax,msg.wParam ret windowmain endp WindowMessageProcessingProcedure proc hwnd:HWND,umsg:UINT,wpar:WPARAM,lpar:LPARAM .IF umsg==WM_DESTROY push NULL call PostQuitMessage .ENDIF xor eax,eax ret WindowMessageProcessingProcedure endp end start P.S это мой первый опыт вообще в программировании на асме, поэтому не судите строго, и в Olly я пока плоховато разбираюсь
Код (Text): WindowMessageProcessingProcedure proc hwnd:HWND,umsg:UINT,wpar:WPARAM,lpar:LPARAM .IF umsg==WM_DESTROY push NULL call PostQuitMessage .ENDIF xor eax,eax ret WindowMessageProcessingProcedure endp Для всех случаев, которые не обрабатываются, должно быть вызвано DefWindowProc. Иначе начнуться проблемы сразу с момента создания окна. Ты обрабатываешь только WM_DESTROY - это самое неважное, что только можно обработать Самое важное - это вызвать DefWindowProc для всех событий, а потом - уже делать специальные обработчики
invoke? Сущая правда. ЗЫ: можешь взять моё, я всем его втюхиваю %) + лучше не выкладывать многостраничные листинги кода прямо на форум, а юзать прикреплённые файлы. И ещё. Товарищи! Структурируйте визуально свой кодес! Он станет намного более читабельным.
Код (Text): .386 .model flat,stdcall option casemap:none include \masm32\include\kernel32.inc include \masm32\include\user32.inc include \masm32\include\windows.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib .data ClassName db "MyClass",0 AppName db "MyApp",0 .data? hInstance HINSTANCE ? CommandLine LPSTR ? .code start: push NULL call GetModuleHandle mov hInstance,eax call GetCommandLine mov CommandLine,eax push NULL push CommandLine push NULL push hInstance call windowmain push eax call ExitProcess windowmain proc hInst:HINSTANCE,pInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL msg:MSG LOCAL hwnd:HWND LOCAL window:WNDCLASSEX mov window.cbSize,SIZEOF WNDCLASSEX mov window.style,CS_HREDRAW or CS_VREDRAW mov window.lpfnWndProc,offset WindowMessageProcessingProcedure push IDC_ARROW push NULL call LoadCursor mov window.hCursor,eax push IDI_APPLICATION push NULL call LoadIcon mov window.hIcon,eax mov window.hIconSm,eax mov window.cbClsExtra,NULL mov window.cbWndExtra,NULL push hInstance pop window.hInstance mov window.hbrBackground,COLOR_WINDOW+1 mov window.lpszMenuName,NULL mov window.lpszClassName,OFFSET ClassName push [window] call RegisterClassEx push offset ClassName push offset AppName push WS_OVERLAPPEDWINDOW push CW_USEDEFAULT push CW_USEDEFAULT push CW_USEDEFAULT push CW_USEDEFAULT push NULL push NULL push hInst push NULL call CreateWindowEx mov hwnd,eax push CmdShow push hwnd call ShowWindow push hwnd call UpdateWindow .WHILE TRUE push 0 push 0 push NULL push msg call GetMessage .BREAK .IF(!eax) push msg call TranslateMessage push msg call DispatchMessage .ENDW mov eax,msg.wParam ret windowmain endp WindowMessageProcessingProcedure proc hwnd:HWND,umsg:UINT,wpar:WPARAM,lpar:LPARAM .IF umsg==WM_DESTROY push NULL call PostQuitMessage .ELSE push lpar push wpar push umsg push hwnd call DefWindowProc .ENDIF xor eax,eax ret WindowMessageProcessingProcedure endp end start Не помогло!
S4urp8n Отдебажил первую часть кода. В частности, всё из-за того, что ты объявил переменную WNDCLASSEX (вместо WNDCLASS, которую и умеет регистрировать RegisterClass [а не RegisterClassЕх]), а во-вторых из-за того что ты её объявил локально, и компиль не догадывается [window] интерпретировать как Код (Text): PUSH EBP; ADD DWORD PTR [ESP], -50h; но есть и другие баги. найду ещё - отпишу.
Тфу ты чёрт. Ни бельмеса я в твоём коде не разберу =( Единственное что могу сказать - ты ещё и параметры в CreateWindowEx передавал не в том порядке что нужно (а нужен, согласно директиве вызова stdcall, обратный порядок: последний параметр кладётся в стэк первым, предпоследний - вторым, итд), и в GetMessage ты передавал не адрес структуры msg, а значение первого её мембера. Ну и напоследок, не совсем ясно, нахренаж тут всё-таки ещё одна процедура, чей код можно совершенно безболезненно вставить вместо Вот. А вообще, дальше разбираться лень. Покорно прошу извинить +) Чесслово, лучше разбирай уже готовый код. И (повторять как мантру) код нужно структурировать, и визуально в том числе! юзать отступы и выделять законченные куски пустыми строками!
GoldFinch хм. Ну я вот применяю invoke, однако от всяких .WHILE и !=еах меня воротит... может, тут подобный случай, только в отношении invoke?
только на след день я понял что для начала нужно пробовать что попроще (это я про invoke) сделал всё заново и прога стала работать как надо Всем СПАСИБО! но все-таки прошу обьяснить что делает DefWindowProc?