Взялся курить исходники Mikl_-а для FASM, но понял, что для меня такое пока рановато... Не въезжаю, приученный к высокоуровневым высказываниям, в простоту ассемблера. ( Итак... Код (Text): format PE GUI entry start include 'win32ax.inc' ; import data in the same section proc Win pop [w] pop [h] xchg ebx,eax mov edi,wTitle mov esi,400000h ; +------------------------------+ ; | registering the window class | ; +------------------------------+ invoke RegisterClass,esp,ebx,WindowProc,ebx,\ ebx,esi,ebx,10011h,COLOR_WINDOW,ebx,edi push ebx push esi push ebx push ebx push [h];WinH push [w];WinW invoke GetSystemMetrics,SM_CYSCREEN sub eax,352 shr eax,1 push eax invoke GetSystemMetrics,SM_CXSCREEN sub eax,512 shr eax,1 ; +--------------------------+ ; | creating the main window | ; +--------------------------+ invoke CreateWindowEx,ebx,edi,edi,WS_OVERLAPPEDWINDOW+WS_VISIBLE,eax mov ebp,esp ret endp start: push 100 push 352 call Win invoke MessageBox,NULL,wTitle,NULL,MB_ICONERROR+MB_OK ; +---------------------------+ ; | entering the message loop | ; +---------------------------+ message_loop: invoke GetMessage,ebp,ebx,ebx,ebx invoke DispatchMessage,ebp jmp message_loop ; +----------------------+ ; | the window procedure | ; +----------------------+ proc WindowProc hwnd,wmsg,wparam,lparam push ebx esi edi cmp [wmsg],WM_DESTROY je .wmdestroy .defwndproc: invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp .finish .wmdestroy: invoke PostQuitMessage,0 xor eax,eax invoke ExitProcess,0 .finish: pop edi esi ebx ret endp wTitle db 'Окошко',0 ;name of our window w dd ? h dd ? data import library KERNEL32, 'KERNEL32.DLL',\ user32, 'USER32.DLL' import KERNEL32,\ ExitProcess, 'ExitProcess' import user32,\ PostQuitMessage, 'PostQuitMessage',\ RegisterClass, 'RegisterClassA',\ CreateWindowEx, 'CreateWindowExA',\ DefWindowProc, 'DefWindowProcA',\ GetMessage, 'GetMessageA',\ DispatchMessage, 'DispatchMessageA',\ MessageBox, 'MessageBoxA',\ GetSystemMetrics, 'GetSystemMetrics' end data Никак не въеду, почему окошко вдруг исчезает. *тупой*
И еще... Как описать и использовать процедуру с несколькими аргументами разного типа??? Код (Text): proc WinCreationProcedure CallBack:DWORD,Title:BYTE,BlaBla:BYTE ... mov edi,[Title] invoke RegisterClass,esp,ebx,[CallBack],ebx,ebx,esi,ebx,10011h,COLOR_WINDOW,ebx,edi ... ret endp ... stdcall [i](или invoke)[/i] Procedure,MyCallBackProc,MyTitle,MyBlaBla ... proc MyCallBackProc hwnd,wmsg,wparam,lparam ... ret endp ... MyTitle db 'Заголовок',0 Такое НЕ работает... (
proc myproc,param1,abc,def,numbeer ret endp под x86 выравнивание лучше делать 4 байта,тоесть dword а не байты а в самой процедуре либо movzx/movsx либо and 0fff...
Код (Text): format PE GUI entry start include 'win32ax.inc' ; import data in the same section proc Win pop [w] pop [h] xchg ebx,eax mov edi,wTitle mov esi,400000h ; +------------------------------+ ; | registering the window class | ; +------------------------------+ invoke RegisterClass,esp,ebx,WindowProc,ebx,\ ebx,esi,ebx,10011h,COLOR_WINDOW,ebx,edi push ebx push esi push ebx push ebx push [h];WinH push [w];WinW invoke GetSystemMetrics,SM_CYSCREEN sub eax,352 shr eax,1 push eax invoke GetSystemMetrics,SM_CXSCREEN sub eax,512 shr eax,1 ; +--------------------------+ ; | creating the main window | ; +--------------------------+ invoke CreateWindowEx,ebx,edi,edi,WS_OVERLAPPEDWINDOW+WS_VISIBLE,eax mov ebp,esp ret endp start: push 100 push 352 call Win invoke MessageBox,NULL,wTitle,NULL,MB_ICONERROR+MB_OK ; +---------------------------+ ; | entering the message loop | ; +---------------------------+ message_loop: invoke GetMessage,ebp,ebx,ebx,ebx invoke DispatchMessage,ebp jmp message_loop ; +----------------------+ ; | the window procedure | ; +----------------------+ proc WindowProc hwnd,wmsg,wparam,lparam push ebx esi edi cmp [wmsg],WM_DESTROY je .wmdestroy .defwndproc: invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp .finish .wmdestroy: invoke PostQuitMessage,0 xor eax,eax invoke ExitProcess,0 .finish: pop edi esi ebx ret endp wTitle db 'Окошко',0 ;name of our window w dd ? h dd ? data import library KERNEL32, 'KERNEL32.DLL',\ user32, 'USER32.DLL' import KERNEL32,\ ExitProcess, 'ExitProcess' import user32,\ PostQuitMessage, 'PostQuitMessage',\ RegisterClass, 'RegisterClassA',\ CreateWindowEx, 'CreateWindowExA',\ DefWindowProc, 'DefWindowProcA',\ GetMessage, 'GetMessageA',\ DispatchMessage, 'DispatchMessageA',\ MessageBox, 'MessageBoxA',\ GetSystemMetrics, 'GetSystemMetrics' end data НАРОД! В чем тут проблема (кроме кривоты моих рук, конечно )??? Почему окошко исчезает только появившись? Спасите нуба - дайте ответ *PLZ*
В поставке FASM есть директория EXAMPLES\TEMPLATE. Сравни код. 1. Сколько параметров в CreateWindowEx()? 2. Как сделан Message Loop? 3. Где вызвана ExitProcess()? Внутри процедуры окна или нет? И ещё (на примере кода): Код (Text): mov eax, esp invoke Procedure1, esp, ebx, esi, edi вопрос: ESP который PUSH-ается первым параметром - равен ли он EAX перед вызовом 'Procedure1'? (Ответ: не равен.)
Если честно, ни хрена не понял. Если может только , не пойму, правда какой его части... А так Код (Text): mov eax, esp invoke Procedure1, esp, ebx, esi, edi выглядит как "Сохранили в EAX значение ESP (количество байтов в стеке, насколько я знаю) перед вызовом процедуры и вызвали саму процедуру, передавая ей первым аргументом, зачем, не знаю (вроде invoke-макрос сам делает это), наше количество байтов в стеке (ESP)... А причем же здесь равно-не равно??? *NOOB* Просто: Код (Text): format PE GUI include 'win32ax.inc' ; import data in the same section xchg ebx,eax mov edi,wTitle mov esi,400000h ; +------------------------------+ ; | registering the window class | ; +------------------------------+ invoke RegisterClass,esp,ebx,window_procedure,ebx,\ ebx,esi,ebx,10011h,COLOR_WINDOW+1,ebx,edi push ebx push esi push ebx push ebx push 352;WinH push 512;WinW invoke GetSystemMetrics,SM_CYSCREEN sub eax,352 shr eax,1 push eax invoke GetSystemMetrics,SM_CXSCREEN sub eax,512 shr eax,1 ; +--------------------------+ ; | creating the main window | ; +--------------------------+ invoke CreateWindowEx,ebx,edi,edi,WS_OVERLAPPEDWINDOW+WS_VISIBLE,eax mov ebp,esp ; +---------------------------+ ; | entering the message loop | ; +---------------------------+ message_loop: invoke GetMessage,ebp,ebx,ebx,ebx invoke DispatchMessage,ebp jmp message_loop ; +----------------------+ ; | the window procedure | ; +----------------------+ window_procedure: cmp dword[esp+0x08],WM_DESTROY je wmDESTROY jmp dword [DefWindowProc] wmDESTROY: invoke ExitProcess,ebx wTitle db 'Iczelion Tutorial #3:A Simple Window in centre in FASM',0 ;name of our window data import library KERNEL32, 'KERNEL32.DLL',\ user32, 'USER32.DLL' import KERNEL32,\ ExitProcess, 'ExitProcess' import user32,\ RegisterClass, 'RegisterClassA',\ CreateWindowEx, 'CreateWindowExA',\ DefWindowProc, 'DefWindowProcA',\ GetMessage, 'GetMessageA',\ DispatchMessage, 'DispatchMessageA',\ GetSystemMetrics, 'GetSystemMetrics' end data - Рабочий код ( (С) Mikl_ ). Я в коде первого поста только закинул процедуры инициализации окна в отдельную процедуру с возможностью указывать высоту и ширину окна не в параметрах процедур инициализации (что я мелю... Надеюсь все читаемо). И теперь окошко появляется и исчезает сразу. Причем в процедуру WindowProc ПОСЫЛАЮТСЯ СООБЩЕНИЯ. Но после создания окна процедурой Win процесс не возвращается в основной код, ведь Код (Text): invoke MessageBox,NULL,wTitle,NULL,MB_ICONERROR+MB_OK не вызывается. Это и есть мое ПОЧЕМУ. P.S. Мое нубское чутье подсказывает, что проблемы неправильном обращении со стеком, но в чем же проблема, мне никак не дойти ( *HELP*
PUSH Очень даже правильно подсказывает. Вообще стоило сначала глянуть в Olly. В самом начале у Вас исполняется код: Код (Text): push 100 push 352 call Win Сколько двойных слов положено в стек? А вот и неправильно. Три: 100, 352 и адрес возврата. Внутри процедуры: Код (Text): pop [w] pop [h] Что снимается с вершины стека? Именно. Снимается адрес возврата и 352. Значит куда попадёт управление после ret'а? Правильно. На Луну. И к тому же перед ret'ом не стоит делать mov ebp,esp, т.к. стек по полученному здесь в ebp адресу в дальнейшем будет использоваться, как буфер для структуры MSG. Т.е. возвращаемая структура будет перекрываться с передаваемым внутрь функций параметром. А это может быть чревато.
Этот код немного с трюками, например, нет использования структур, а просто поля структуры идут в стек и затем ESP идёт как адрес структуры - красиво, но читать такой код трудновато. Я бы посоветовал учиться на более удобоваримом коде - например из поставки FASM. Почему окно исчезает - не понятно. P.S. RegisterClass() чистит за собой 4 байта (один DWORD параметер), так что попробуй почистить остальное занесённое при этом вызове (размер структуры WNDCLASS). Если этого не сделать, то адрес возврата из Win будет не в нужном месте.
l_inc Метко. *РЖУниМаГУ* Запатентуй. ) Код (Text): format PE GUI entry start include 'win32ax.inc' ; import data in the same section proc Win pop [adr] pop [w] pop [h] xchg ebx,eax mov edi,wTitle mov esi,400000h ; +------------------------------+ ; | registering the window class | ; +------------------------------+ invoke RegisterClass,esp,ebx,WindowProc,ebx,\ ebx,esi,ebx,10011h,COLOR_WINDOW,ebx,edi push ebx push esi push ebx push ebx push [h];WinH push [w];WinW invoke GetSystemMetrics,SM_CYSCREEN sub eax,352 shr eax,1 push eax invoke GetSystemMetrics,SM_CXSCREEN sub eax,512 shr eax,1 ; +--------------------------+ ; | creating the main window | ; +--------------------------+ invoke CreateWindowEx,ebx,edi,edi,WS_OVERLAPPEDWINDOW+WS_VISIBLE,eax mov ebp,esp push [adr] ret endp start: push 100 push 352 call Win invoke MessageBox,NULL,wTitle,NULL,MB_ICONERROR+MB_OK ; +---------------------------+ ; | entering the message loop | ; +---------------------------+ message_loop: invoke GetMessage,ebp,ebx,ebx,ebx invoke DispatchMessage,ebp jmp message_loop ; +----------------------+ ; | the window procedure | ; +----------------------+ proc WindowProc hwnd,wmsg,wparam,lparam ;invoke MessageBox,NULL,wTitle,NULL,MB_ICONERROR+MB_OK push ebx esi edi cmp [wmsg],WM_DESTROY je .wmdestroy .defwndproc: invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp .finish .wmdestroy: invoke PostQuitMessage,0 xor eax,eax invoke ExitProcess,0 .finish: pop edi esi ebx ret endp wTitle db 'Окошко',0 ;name of our window w dd ? h dd ? adr dd ? data import library KERNEL32, 'KERNEL32.DLL',\ user32, 'USER32.DLL' import KERNEL32,\ ExitProcess, 'ExitProcess' import user32,\ PostQuitMessage, 'PostQuitMessage',\ RegisterClass, 'RegisterClassA',\ CreateWindowEx, 'CreateWindowExA',\ DefWindowProc, 'DefWindowProcA',\ GetMessage, 'GetMessageA',\ DispatchMessage, 'DispatchMessageA',\ MessageBox, 'MessageBoxA',\ GetSystemMetrics, 'GetSystemMetrics' end data ЗАРАБОТАЛО!!! Окно исчезает из-за перенаправления "на луну" (С) l_inc. Я ж и не заметил, что окошко первого поста по ширине уехало аж за экран. Теперь усэ понятно. Сохранили адрес из стека и восстановили его прямо перед ret-ом. Но теперь еще вопросы: Получается push и pop при работе с памятью требуют адрес, а не значение. Так? Если да, то я НАКОНЕЦ ТО ВКУРИЛ. БУГАГА!!! Всем БОЛЬШОЙ-ПРЕБОЛЬШОЙ СПАСИБ за проявленное терпение.
PUSH Почему у тебя такое низкое о себе мнение, кривые руки, нуб.. это приводит к отсутствию самонадеянности..
"Нуб" и "Кривые руки" - самотонус к познанию ... Типа "аутотренинг через отрицание и все такое". (Фрейд, дружище, где же ты ) Короче, сам себя не поругаешь, никто не похвалит (С) PUSH CrystalIC Надо бы тоже почитать сорцы Винды, доки и посидеть в дизасме, мож тоже стану ЭЛИТОЙ
Жесть.. когда я то читал катался по полу от смеха; смысл не в том, я к тому что: Под отладчиком ведь всё видно что куда идёт, не то что замечание, просто полезный совет.
И снова ОНО! Теперь вынес процедуру создания окна в отдельную библиотеку и вызвал экспортированную функцию из проги-проверки. Результат в Олли - отправили данные в стек, но достали СОВСЕМ НЕ ТО. Итог - опять лажа. Представляю на ваш суд совмещенный РАБОЧИЙ код: Код (Text): format PE GUI entry start include 'win32a.inc' ; import data in the same section proc Win pop [adr] pop [t] pop [CB] pop [w] pop [h] xchg ebx,eax mov edi,[t] mov esi,400000h ; +------------------------------+ ; | registering the window class | ; +------------------------------+ invoke RegisterClass,esp,ebx,[CB],ebx,\ ebx,esi,ebx,10011h,COLOR_WINDOW,ebx,edi push ebx push esi push ebx push ebx push [h];WinH push [w];WinW invoke GetSystemMetrics,SM_CYSCREEN sub eax,352 shr eax,1 push eax invoke GetSystemMetrics,SM_CXSCREEN sub eax,512 shr eax,1 ; +--------------------------+ ; | creating the main window | ; +--------------------------+ invoke CreateWindowEx,ebx,edi,edi,WS_OVERLAPPEDWINDOW+WS_VISIBLE,eax mov ebp,esp push [adr] ret endp start: stdcall Win,wTitle,WindowProc,352,100 ; +---------------------------+ ; | entering the message loop | ; +---------------------------+ message_loop: invoke GetMessage,ebp,ebx,ebx,ebx mov eax,99 ;mov ebx,2 mov edx,56 invoke DispatchMessage,ebp jmp message_loop ; +----------------------+ ; | the window procedure | ; +----------------------+ proc WindowProc hwnd,wmsg,wparam,lparam ;invoke MessageBox,NULL,wTitle,NULL,MB_ICONERROR+MB_OK push ebx esi edi cmp [wmsg],WM_DESTROY je .wmdestroy .defwndproc: invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp .finish .wmdestroy: invoke PostQuitMessage,0 xor eax,eax invoke ExitProcess,0 .finish: pop edi esi ebx ret endp wTitle db 'Окошко',0 ;name of our window t dd ? w dd ? h dd ? CB dd ? adr dd ? data import library KERNEL32, 'KERNEL32.DLL',\ user32, 'USER32.DLL' import KERNEL32,\ ExitProcess, 'ExitProcess' import user32,\ PostQuitMessage, 'PostQuitMessage',\ RegisterClass, 'RegisterClassA',\ CreateWindowEx, 'CreateWindowExA',\ DefWindowProc, 'DefWindowProcA',\ GetMessage, 'GetMessageA',\ DispatchMessage, 'DispatchMessageA',\ MessageBox, 'MessageBoxA',\ GetSystemMetrics, 'GetSystemMetrics' end data и два РАЗДЕЛЕННЫХ, проблема, как мне кажется в коде БИБЛИОТЕКИ: Код (Text): format PE GUI 4.0 DLL entry DllEntryPoint include 'win32a.inc' ; import data in the same section proc DllEntryPoint hinstDLL,fdwReason,lpvReserved mov eax,TRUE ret endp proc Win,t,CB,w,h ;pop [adr] ;pop [t] ;pop [CB] ;pop [w] ;pop [h] xchg ebx,eax mov edi,[t] mov esi,400000h ; +------------------------------+ ; | registering the window class | ; +------------------------------+ invoke RegisterClass,esp,ebx,[CB],ebx,\ ebx,esi,ebx,10011h,COLOR_WINDOW,ebx,edi push ebx push esi push ebx push ebx push [h];WinH push [w];WinW invoke GetSystemMetrics,SM_CYSCREEN sub eax,352 shr eax,1 push eax invoke GetSystemMetrics,SM_CXSCREEN sub eax,512 shr eax,1 ; +--------------------------+ ; | creating the main window | ; +--------------------------+ invoke CreateWindowEx,ebx,edi,edi,WS_OVERLAPPEDWINDOW+WS_VISIBLE,eax mov ebp,esp push [adr] ret endp t dd ? w dd ? h dd ? CB dd ? adr dd ? data import library KERNEL32, 'KERNEL32.DLL',\ user32, 'USER32.DLL' import KERNEL32,\ ExitProcess, 'ExitProcess' import user32,\ PostQuitMessage, 'PostQuitMessage',\ RegisterClass, 'RegisterClassA',\ CreateWindowEx, 'CreateWindowExA',\ DefWindowProc, 'DefWindowProcA',\ GetMessage, 'GetMessageA',\ DispatchMessage, 'DispatchMessageA',\ MessageBox, 'MessageBoxA',\ GetSystemMetrics, 'GetSystemMetrics' end data section '.edata' export data readable export 'MM_GUI.DLL',\ Win,'Win' section '.reloc' fixups data discardable Код (Text): format PE GUI 4.0 entry start include 'win32a.inc' section '.code' code readable executable proc WindowProc hwnd,wmsg,wparam,lparam push ebx esi edi cmp [wmsg],2; 2=WM_DESTROY je .wmdestroy .defwndproc: invoke DefWindowProc,[hwnd],[wmsg],[wparam],[lparam] jmp .finish .wmdestroy: invoke PostQuitMessage,0 xor eax,eax invoke ExitProcess,0 .finish: pop edi esi ebx ret endp wTitle db 'Iczelion Tutorial #3:A Simple Window in centre in FASM',0 start: invoke Win,wTitle,WindowProc,352,100 message_loop: invoke GetMessage,ebp,ebx,ebx,ebx invoke DispatchMessage,ebp jmp message_loop section '.idata' import data readable writeable library KERNEL32, 'KERNEL32.DLL',\ user32, 'USER32.DLL',\ mmgui, 'MM_GUI.DLL' import KERNEL32,\ ExitProcess, 'ExitProcess' import user32,\ PostQuitMessage, 'PostQuitMessage',\ RegisterClass, 'RegisterClassA',\ CreateWindowEx, 'CreateWindowExA',\ DefWindowProc, 'DefWindowProcA',\ GetMessage, 'GetMessageA',\ DispatchMessage, 'DispatchMessageA',\ MessageBox, 'MessageBoxA',\ GetSystemMetrics, 'GetSystemMetrics' import mmgui,\ Win,'Win' ПАМАГИТЕ!!! Мой маленький мозг пока это сам осилить не может