Доброе время суток. Начал изучать ассемблер, в среде МАСМ. Столкнулся с проблемой... Пишу простое приложение, кторое должно создавать окно, библиотечными вин-функциями. Вот какой код у меня получился: Код (Text): .386p .MODEL FLAT, STDCALL ; ------------------------------------------------------------------------- EXTERN MessageBoxA@16:near EXTERN CreateWindowExA@48:near EXTERN DefWindowProcA@16:near EXTERN DispatchMessageA@4:near EXTERN ExitProcess@4:near EXTERN GetMessageA@16:near EXTERN GetModuleHandleA@4:near EXTERN PostQuitMessage@4:near EXTERN RegisterClassA@4:near EXTERN ShowWindow@8:near EXTERN TranslateMessage@4:near EXTERN UpdateWindow@4:near EXTERN LoadCursorA@8:NEAR EXTERN LoadIconA@8:NEAR includelib lib\kernel32.lib includelib lib\user32.lib wndclass struc classstyle dd ? clwndproc dd ? clscextra dd ? clwndextra dd ? clshinstance dd ? clshicon dd ? clshcursor dd ? clbground dd ? clmenuname dd ? clname dd ? wndclass ends msgs struc mshwnd dd ? msmessage dd ? mswparam dd ? mslparam dd ? mstime dd ? mspt dd ? msgs ends .data classname db 'ASMCLASS32',0 titlename db 'win win win hehehe',0 hinst dd 00000000h wc wndclass <?> nhwnd dd 0 msg msgs <?> cap db 'message!',0 textmess db 'r button!',0 textmess2 db 'CREATE!!!!',0 ; ------------------------------------------------------------------------- .code START: push 0 call GetModuleHandleA@4 mov [hinst],eax mov [wc.classstyle],4003h mov [wc.clwndproc],offset wndproc mov [wc.clscextra],0 mov [wc.clwndextra],0 mov eax,[hinst] mov [wc.clshinstance],eax push 32512 push 0 call LoadIconA@8 mov [wc.clshicon],eax push 32512 push 0 call LoadCursorA@8 mov [wc.clshcursor],eax mov [wc.clbground],5 mov dword ptr [wc.clmenuname],0 mov dword ptr [wc.clname],offset classname push offset wc call RegisterClassA@4 push 0 push [hinst] push 0 push 0 push 80000000h push 80000000h push 80000000h push 80000000h push 0CF0000h push offset titlename push offset classname push 0 call CreateWindowExA@48 mov [nhwnd],eax push 1 push [nhwnd] call ShowWindow@8 push [nhwnd] call UpdateWindow@4 msg_loop: push 0 push 0 push 0 push offset msg call GetMessageA@16 cmp ax,0 jz end_loop push offset msg call TranslateMessage@4 push offset msg call DispatchMessageA@4 jmp msg_loop end_loop: push 0 call ExitProcess@4 ; ------------------------------------------------------------------------- wndproc proc push ebp mov ebp,esp push ebx push esi push edi cmp dword ptr [ebp+0Ch],2h jz wmdestroy cmp dword ptr [ebp+0Ch],1h jz wmcreate cmp dword ptr [ebp+0Ch],204 jz wmrbutton push dword ptr [ebp+14h] push dword ptr [ebp+10h] push dword ptr [ebp+0Ch] push dword ptr [ebp+08h] call DefWindowProcA@16 mov eax,0 jmp finish wmcreate: push offset cap push offset textmess2 call mess mov eax,0 jmp finish wmrbutton: push offset cap push offset textmess call mess mov eax,0 jmp finish wmdestroy: push 0 call PostQuitMessage@4 mov eax,0 finish: pop edi pop esi pop ebx pop ebp ret 16 wndproc endp mess proc push ebp mov ebp,esp push 0 push dword ptr [ebp+12] push dword ptr [ebp+8] push 0 call MessageBoxA@16 mov esp,ebp pop ebx ret 8 mess endp END START в коде я старался не использовать директив, типа Инвок и прочих - делающих асм похожим на язык высокого уровня. Код, что я привёл, вроде как и правильный, но не работает. А почему не раюотает - не знаю, не могу найти ошибку. Смотрел в отладчике - после функции CreateWindowExA в ЕАХ помещается 0, следовательно - ошибка. Но ведь там всё правильно... Качаю пример, компилирую, смотрю в отладчике - всё тоже самое, но работает. а мой - не хочет... Подскажите в чём я ошибся... вот пример, который работает: Код (Text): .386p .model flat, stdcall option casemap:none includelib .\lib\kernel32.lib includelib .\lib\user32.lib include .\include\windows.inc include .\include\kernel32.inc include .\include\user32.inc .data newhwnd dd 0 hInst dd 00000000h szTitleName db 'Window Application',0 szClassName db 'ASMCLASS32',0 msg MONMSGSTRUCT <?> ; структура сообщения wc WNDCLASS <?> ; структура класса .code start: Invoke GetModuleHandle,0 ; получаем hInstanse Mov [hInst], eax Mov [wc.style], CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS ; устанавливаем стиль окна Mov [wc.lpfnWndProc], offset WndProc ; Mov [wc.cbClsExtra], 0 Mov [wc.cbWndExtra], 0 Mov eax, [hInst] Mov [wc.hInstance], eax Invoke LoadIcon,0,IDI_APPLICATION ; получаем значок приложения по ; умолчанию Mov [wc.hIcon], eax Invoke LoadCursorA,0,IDC_ARROW ; получаем курсор по умолчанию Mov [wc.hCursor], eax Mov [wc.hbrBackground], 5 Mov dword ptr [wc.lpszMenuName], 0 Mov dword ptr [wc.lpszClassName], offset szClassName ; задаём имя класса ;окна Invoke RegisterClassA,offset wc ; регистрируем класс окна Push 0 Push [hInst] ; дескриптор Push 0 Push 0 Push CW_USEDEFAULT ; высота Push CW_USEDEFAULT ; ширина Push CW_USEDEFAULT ; y Push CW_USEDEFAULT ; x Push WS_OVERLAPPEDWINDOW ; стиль Push offset szTitleName ; заголовок окна Push offset szClassName ; имя класса Push 0 ; дополнительный стиль Call CreateWindowEx ; создаём окно mov [newhwnd], eax ; сохраняем его дескриптор invoke ShowWindow,[newhwnd],SW_SHOWNORMAL; показываем окно invoke UpdateWindow, [newhwnd]; обновляем его msg_loop: ; запускаем цикл обработки сообщений invoke GetMessage,offset msg, 0,0,0 cmp ax, 0 je end_loop invoke TranslateMessage, offset msg invoke DispatchMessage, offset msg jmp msg_loop end_loop: invoke ExitProcess, 0 WndProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD Cmp [wmsg], WM_DESTROY Je wmdestroy Cmp [wmsg], WM_KEYDOWN Je wmkeydown Invoke DefWindowProcA,[hwnd],[wmsg],[wparam],[lparam] ; вызываем стандартный обработчик сообщений Jmp finish wmkeydown: cmp [wparam], VK_ESCAPE je wmdestroy; если нажата клавиша Escape то выход jmp finish wmdestroy: invoke PostQuitMessage, 0 invoke ExitProcess, 0 ; выход finish: ret WndProc endp end start
splinter Зачем wndproc proc, если дальше всё равно вручную mov ebp,esp. Да кстати у тебя в конце pop ebx, а должно быть pop ebp. Попробуй так: Код (Text): wndproc: push ebp mov ebp,esp leave ret 16 К томуже по-моему [hwnd] - это [ebp+4], а у тебя [ebp+8]
В вашем: Код (Text): call DefWindowProcA@16 mov eax,0 ; репрессировать! jmp finish В рабочем: Код (Text): invoke PostQuitMessage, 0 invoke ExitProcess, 0 ; выход - в странном месте murder [ebp+4] - адрес возврата) splinter может, понравятся опции Код (Text): option prologue: none option epilogue: none если уж все равно вручную создаем фреймы)
splinter Если охота эксперементировать -- возьми работающий пример и замени первую строку, что бы было как в твоем примере, компилируй, запускай, работает -- меняешь следующую строку и так далее... А вообще-то, поиск по wasm.ru/forum раздел WASM.BEGINNERS -- ищи "третий урок Iczelion'а" и смотри кто с какими ошибками сталкивался при его написании и как их исправляли
splinter вдогонку: WM_RBUTTONDOWN - он 204h, иначе у вас не вылезет окошко по правой кнопке. Ну и структуру msgs неверно описали - посмотрите, как себя ведет заголовок этого окошка. На самом деле последний элемент структуры - POINT, а в ней два поля dword, так что Код (Text): msgs struc mshwnd dd ? msmessage dd ? mswparam dd ? mslparam dd ? mstime dd ? mspt dd ? dd ? msgs ends
дадада! ну эт разницы нет, так как после компиляции одно и тоже выходит Да, исправил, спасибо! Где можно про это подробней почитать? Просто вроде как верно... Но всё равно главная ошибка в функции CreateWindowExA, так как после неё в ЕАХ заносится 0 - в Ольке смотрел. Вот после небольших исправлений что поучилось: Код (Text): .386p .MODEL FLAT, STDCALL ; ------------------------------------------------------------------------- EXTERN MessageBoxA@16:near EXTERN CreateWindowExA@48:near EXTERN DefWindowProcA@16:near EXTERN DispatchMessageA@4:near EXTERN ExitProcess@4:near EXTERN GetMessageA@16:near EXTERN GetModuleHandleA@4:near EXTERN PostQuitMessage@4:near EXTERN RegisterClassA@4:near EXTERN ShowWindow@8:near EXTERN TranslateMessage@4:near EXTERN UpdateWindow@4:near EXTERN LoadCursorA@8:NEAR EXTERN LoadIconA@8:NEAR includelib lib\kernel32.lib includelib lib\user32.lib wndclass struc classstyle dd ? clwndproc dd ? clscextra dd ? clwndextra dd ? clshinstance dd ? clshicon dd ? clshcursor dd ? clbground dd ? clmenuname dd ? clname dd ? wndclass ends msgs struc mshwnd dd ? msmessage dd ? mswparam dd ? mslparam dd ? mstime dd ? mspt dd ? msgs ends .data classname db 'ASMCLASS32',0 titlename db 'win win win hehehe',0 hinst dd 00000000h wc wndclass <?> nhwnd dd 0 msg msgs <?> cap db 'message!',0 textmess db 'r button!',0 textmess2 db 'CREATE!!!!',0 ; ------------------------------------------------------------------------- .code START: push 0 call GetModuleHandleA@4 mov [hinst],eax mov [wc.classstyle],4003h mov [wc.clwndproc],offset wndproc mov [wc.clscextra],0 mov [wc.clwndextra],0 mov eax,[hinst] mov [wc.clshinstance],eax push 32512 push 0 call LoadIconA@8 mov [wc.clshicon],eax push 32512 push 0 call LoadCursorA@8 mov [wc.clshcursor],eax mov [wc.clbground],5 mov dword ptr [wc.clmenuname],0 mov dword ptr [wc.clname],offset classname push offset wc call RegisterClassA@4 push 0 push [hinst] push 0 push 0 push 80000000h push 80000000h push 80000000h push 80000000h push 0CF0000h push offset titlename push offset classname push 0 call CreateWindowExA@48 mov [nhwnd],eax push 1 push [nhwnd] call ShowWindow@8 push [nhwnd] call UpdateWindow@4 msg_loop: push 0 push 0 push 0 push offset msg call GetMessageA@16 cmp ax,0 jz end_loop push offset msg call TranslateMessage@4 push offset msg call DispatchMessageA@4 jmp msg_loop end_loop: push 0 call ExitProcess@4 ; ------------------------------------------------------------------------- wndproc proc push ebp mov ebp,esp push ebx push esi push edi cmp dword ptr [ebp+0Ch],2h jz wmdestroy cmp dword ptr [ebp+0Ch],1h jz wmcreate cmp dword ptr [ebp+0Ch],204h jz wmrbutton push dword ptr [ebp+14h] push dword ptr [ebp+10h] push dword ptr [ebp+0Ch] push dword ptr [ebp+08h] call DefWindowProcA@16 mov eax,0 jmp finish wmcreate: push offset cap push offset textmess2 call mess mov eax,0 jmp finish wmrbutton: push offset cap push offset textmess call mess mov eax,0 jmp finish wmdestroy: push 0 call PostQuitMessage@4 mov eax,0 finish: pop edi pop esi pop ebx pop ebp ret 16 wndproc endp mess proc push ebp mov ebp,esp push 0 push dword ptr [ebp+12] push dword ptr [ebp+8] push 0 call MessageBoxA@16 mov esp,ebp pop ebp ret 8 mess endp END START Всё равно - окно не создаётся... Может посмотрите, кто, с исправлениями запостьте... Буду очень признателен
splinter Ты уверен ? Если не отключить опции создания пролога\эпилога, то макрос proc сам создает стековый фрейм (push ebp и т.д.). Поэтому, если еще и ты добавляешь свой push ebp, то реальные смещения всех параметров в стеке относительно ebp увеличиваются на 4
Попробуй Код (Text): SetWindowLong(CreateWindowEx(0,'STATIC',0,WS_OVERLAPPEDWINDOW+WS_VISIBLE,80000000h,80000000h,80000000h,80000000h,0,0,0,0),GWL_WNDPROC,wndproc); Ненадо никакого RegisterClass, ShowWindow, UpdateWindow
splinter после вызова DefWindowProc ни в коем случае не надо сбрасывать еах в ноль! А то WM_NCCREATE возвращает ноль, а не единицу, и создание окна рушится почитать про структуры - в windows.inc или в справке по winapi
Использую МАСМ 2008 (10 вроде), настройки по дефолту Дабы это проверить создал листинг: Код (Text): .586p .MODEL FLAT, STDCALL .data var1 dd 12h .code START: push var1 call sss sss proc push ebp mov ebp,esp mov eax,[ebp+4] ret sss endp END START В ольке видим: Код (Text): PUSH DWORD PTR DS:[402000] CALL 0040100B PUSH EBP MOV EBP,ESP MOV EAX,DWORD PTR SS:[EBP+4] RETN В примере, рабочем, что я постил выше написано: Код (Text): Push CW_USEDEFAULT ; высота Push CW_USEDEFAULT ; ширина Push CW_USEDEFAULT ; y Push CW_USEDEFAULT ; x смотрим в windows.inc и видим, что константа CW_USEDEFAULT - 80000000h СПАСИБО ОГРОМНОЕ, ДРУЖИЩЕ!!! Это и была моя ошибка, которую я не мог найти! Окно создалось, всё работает как надо! выходной код: Код (Text): .386p .MODEL FLAT, STDCALL ; ------------------------------------------------------------------------- EXTERN MessageBoxA@16:near EXTERN CreateWindowExA@48:near EXTERN DefWindowProcA@16:near EXTERN DispatchMessageA@4:near EXTERN ExitProcess@4:near EXTERN GetMessageA@16:near EXTERN GetModuleHandleA@4:near EXTERN PostQuitMessage@4:near EXTERN RegisterClassA@4:near EXTERN ShowWindow@8:near EXTERN TranslateMessage@4:near EXTERN UpdateWindow@4:near EXTERN LoadCursorA@8:NEAR EXTERN LoadIconA@8:NEAR includelib lib\kernel32.lib includelib lib\user32.lib wndclass struc classstyle dd ? clwndproc dd ? clscextra dd ? clwndextra dd ? clshinstance dd ? clshicon dd ? clshcursor dd ? clbground dd ? clmenuname dd ? clname dd ? wndclass ends msgs struc mshwnd dd ? msmessage dd ? mswparam dd ? mslparam dd ? mstime dd ? mspt dd ? dd ? msgs ends .data classname db 'ASMCLASS32',0 titlename db 'win win win hehehe',0 hinst dd 00000000h wc wndclass <?> nhwnd dd 0 msg msgs <?> cap db 'message!',0 textmess db 'r button!',0 textmess2 db 'CREATE!!!!',0 ; ------------------------------------------------------------------------- .code START: push 0 call GetModuleHandleA@4 mov [hinst],eax mov [wc.classstyle],4003h mov [wc.clwndproc],offset wndproc mov [wc.clscextra],0 mov [wc.clwndextra],0 mov eax,[hinst] mov [wc.clshinstance],eax push 32512 push 0 call LoadIconA@8 mov [wc.clshicon],eax push 32512 push 0 call LoadCursorA@8 mov [wc.clshcursor],eax mov [wc.clbground],5 mov dword ptr [wc.clmenuname],0 mov dword ptr [wc.clname],offset classname push offset wc call RegisterClassA@4 push 0 push [hinst] push 0 push 0 push 80000000h push 80000000h push 80000000h push 80000000h push 0CF0000h push offset titlename push offset classname push 0 call CreateWindowExA@48 mov [nhwnd],eax push 1 push [nhwnd] call ShowWindow@8 push [nhwnd] call UpdateWindow@4 msg_loop: push 0 push 0 push 0 push offset msg call GetMessageA@16 cmp ax,0 jz end_loop push offset msg call TranslateMessage@4 push offset msg call DispatchMessageA@4 jmp msg_loop end_loop: push 0 call ExitProcess@4 ; ------------------------------------------------------------------------- wndproc proc push ebp mov ebp,esp push ebx push esi push edi cmp dword ptr [ebp+0Ch],2h jz wmdestroy cmp dword ptr [ebp+0Ch],1h jz wmcreate cmp dword ptr [ebp+0Ch],204h jz wmrbutton push dword ptr [ebp+14h] push dword ptr [ebp+10h] push dword ptr [ebp+0Ch] push dword ptr [ebp+08h] call DefWindowProcA@16 jmp finish wmcreate: push offset cap push offset textmess2 call mess mov eax,0 jmp finish wmrbutton: push offset cap push offset textmess call mess mov eax,0 jmp finish wmdestroy: push 0 call PostQuitMessage@4 mov eax,0 finish: pop edi pop esi pop ebx pop ebp ret 16 wndproc endp mess proc push ebp mov ebp,esp push 0 push dword ptr [ebp+12] push dword ptr [ebp+8] push 0 call MessageBoxA@16 mov esp,ebp pop ebp ret 8 mess endp END START
Дабы не мусорить и не создавать новую тему, поднял старую, так как опять что-то пошло не так... Проблема в том, что не загружается меню с ресурса и де ошибка не могу найти... вот листинг: Код (Text): .586p .MODEL FLAT, STDCALL ; ------------------------------------------------------------------------- EXTERN MessageBoxA@16:near EXTERN CreateWindowExA@48:near EXTERN DefWindowProcA@16:near EXTERN DispatchMessageA@4:near EXTERN ExitProcess@4:near EXTERN GetMessageA@16:near EXTERN GetModuleHandleA@4:near EXTERN PostQuitMessage@4:near EXTERN RegisterClassA@4:near EXTERN ShowWindow@8:near EXTERN TranslateMessage@4:near EXTERN UpdateWindow@4:near EXTERN LoadCursorA@8:NEAR EXTERN LoadIconA@8:NEAR EXTERN SetMenu@8:NEAR EXTERN LoadMenuA@8:NEAR includelib C:\masm32\lib\kernel32.lib includelib C:\masm32\lib\user32.lib wndclass struc classstyle dd ? clwndproc dd ? clscextra dd ? clwndextra dd ? clshinstance dd ? clshicon dd ? clshcursor dd ? clbground dd ? clmenuname dd ? clname dd ? wndclass ends msgs struc mshwnd dd ? msmessage dd ? mswparam dd ? mslparam dd ? mstime dd ? mspt dd ? dd ? msgs ends .data classname db 'ASMCLASS32',0 titlename db 'win win win hehehe',0 hinst dd 00000000h wc wndclass <?> nhwnd dd 0 msg msgs <?> cap db 'message!',0 textmess db 'r button!',0 textmess2 db 'CREATE!!!!',0 pmenu db 'MENUP',0 ; ------------------------------------------------------------------------- .code START: push 0 call GetModuleHandleA@4 mov [hinst],eax mov [wc.classstyle],4003h mov [wc.clwndproc],offset wndproc mov [wc.clscextra],0 mov [wc.clwndextra],0 mov eax,[hinst] mov [wc.clshinstance],eax push 32512 push 0 call LoadIconA@8 mov [wc.clshicon],eax push 32512 push 0 call LoadCursorA@8 mov [wc.clshcursor],eax mov [wc.clbground],5 mov dword ptr [wc.clmenuname],0 mov dword ptr [wc.clname],offset classname push offset wc call RegisterClassA@4 push 0 push [hinst] push 0 push 0 push 80000000h push 80000000h push 80000000h push 80000000h push 0CF0000h push offset titlename push offset classname push 0 call CreateWindowExA@48 mov [nhwnd],eax push 1 push [nhwnd] call ShowWindow@8 push [nhwnd] call UpdateWindow@4 msg_loop: push 0 push 0 push 0 push offset msg call GetMessageA@16 cmp ax,0 jz end_loop push offset msg call TranslateMessage@4 push offset msg call DispatchMessageA@4 jmp msg_loop end_loop: push 0 call ExitProcess@4 ; ------------------------------------------------------------------------- wndproc proc push ebp mov ebp,esp push ebx push esi push edi cmp dword ptr [ebp+0Ch],2h jz wmdestroy cmp dword ptr [ebp+0Ch],1h jz wmcreate cmp dword ptr [ebp+0Ch],204h jz wmrbutton ;============================================================================================== cmp dword ptr [ebp+0CH],111h jne defw cmp dword ptr [ebp+10h],5 jz wmdestroy defw: push dword ptr [ebp+14h] push dword ptr [ebp+10h] push dword ptr [ebp+0Ch] push dword ptr [ebp+08h] call DefWindowProcA@16 jmp finish wmcreate: push offset pmenu push hinst call LoadMenuA@8 push eax push dword ptr [ebp+08h] call SetMenu@8 mov eax,0 jmp finish wmrbutton: push offset cap push offset textmess call mess mov eax,0 jmp finish wmdestroy: push 0 call PostQuitMessage@4 mov eax,0 finish: pop edi pop esi pop ebx pop ebp ret 16 wndproc endp mess proc push ebp mov ebp,esp push 0 push dword ptr [ebp+12] push dword ptr [ebp+8] push 0 call MessageBoxA@16 mov esp,ebp pop ebp ret 8 mess endp END START а вот листинг ресурса: Код (Text): MENUP MENU { POPUP "ПЕРВЫЙ ПУНКТ" { MENUITEM "ПЕРВЫЙ",1 MENUITEM "ВТОРОЙ",2,GRAYED POPUP "ПОДМЕНЮ" { MENUITEM "ДЕСЯТКА",6 } } POPUP "ВТОРОЙ ПУНКТ" { MENUITEM "ТРЕТИЙ",3 MENUITEM "ЧЕТВЁРТЫЙ",4 } MENUITEM "ВЫХОД",5 } спасибо огромное, кто поможет или попробует это сделать...
splinter Взял твой код и ресурс из #14, в коде подправил пути к kernel32.lib и user32.lib, собрал, запускаю - окно с менюшкой. Что я сделал не так?
splinter Microsoft (R) Macro Assembler Version 6.15.8803 Microsoft (R) Windows (R) Resource Compiler, Version 5.00.1823.1 - Build 1823 Microsoft (R) Incremental Linker Version 5.12.8078 Инклюды и библиотеки из The MASM32 SDK version 10.
хм... пишу в коммандной строке: c:\masm32\bin\ml.exe /c /coff c:\masm32\11.asm и не создаётся obj-файл... и линкер тож.. Пишу: с:\masm32\bin\link.exe /subsystem:windows c:\masm32\11.obj c:\masm32\11.res не создаёт ехе файл Только если компилирую через qeditor.exe (Project -> Build all) всё получается... В чём может быть проблема? ЗЫ Извиняюсь за свою бестактность, программировать на ассемблере начал недавно, раньше только на высокоуровневых языках...
splinter > не создаётся obj-файл... Что пишет компилятор? > не создаёт ехе файл Что пишет редактор связей? Как создаешь res-файл?