Объясните, пожалуйста, почему первый код работает, а второй нет: (1) Код (Text): WindowProc proc, Window, msg, wParam, lParam: DWORD cmp msg, WM_DESTROY jne @f push 0 call PostQuitMessage @@: push lParam push wParam push msg push Window call DefWindowProc ret WindowProc endp (2) Код (Text): .data Window dd 0 msg dd 0 wParam dd 0 lParam dd 0 .code WindowProc proc mov eax, [ebp + 8] mov Window, eax mov eax, [ebp + 12] mov msg, eax mov eax, [ebp + 16] mov wParam, eax mov eax, [ebp + 20] mov lParam, eax cmp msg, WM_DESTROY jne @f push 0 call PostQuitMessage @@: push lParam push wParam push msg push Window call DefWindowProc ret WindowProc endp Никак не могу понять
Пробуем в конце Код (Text): leave ret 10h если не получится, то плюс к этому в начале Код (Text): push ebp mov ebp, esp
Большое спасибо! Работает в 2х случаях: Код (Text): WindowProc proc push ebp mov ebp, esp ... leave ret 0 WindowProc endp и Код (Text): WindowProc proc push ebp mov ebp, esp ... mov esp, ebp pop ebp ret 0 WindowProc endp (и не нужно никаких 10h). Выходит, что Leave это тоже самое что "mov esp, ebp; pop ebp"?
А вообще всё работает гораздо проще! Код (Text): .data Window dd 0 msg dd 0 wParam dd 0 lParam dd 0 .code WindowProc proc pop edx pop Window pop msg pop wParam pop lParam push edx cmp msg, WM_DESTROY jne @f push 0 call PostQuitMessage @@: push lParam push wParam push msg push Window call DefWindowProc ret WindowProc endp
Тогда уж еще проще Код (Text): proc WindowProc mov eax,[esp+8] ; eax - msg cmp eax,WM_DESTROY je @@destroy lea eax,[DefWindowProc] jmp eax @@destroy: push 0 call call PostQuitMessage ret 10h endp
JAPH, у меня был похожий косяк, тоже забыл поставить очистку стека Но поскольку никогда не использую ebp (обращаюсь напрямую через esp), то прога успешно работала несколько суток, после чего благополучно упала Бывает
Круто! Наверно надо не один год кодить, чтоб так придумать Я понял, ret 10h увеличивает esp Только непонятно... почему так долго? какой тогда размер стэка?
Я и начинал еще с убогих советских А так долго проработала из-за того, что DefWindowProc, в подавляющем большинстве случаев, сам очищал мой стэк, размер которого был минимален
Кстати, ещё один тупой вопрос про стэк Правда ли, что работа с переменными в стэке происходит быстрее, чем с глобальными переменными? Если да, то почему?
Дада, именно так. Еще есть парная команда ENTER X,X которая заменяет PUSH EBP / MOV EBP,ESP / SUB..., но вроде бы она медленнее, чем push/mov/sub. Так что компиляторы обычно как пролог пишут явно PUSH EBP/MOV EBP,ESP а как эпилог - LEAVE
Zmiy Да, обычно стек работает быстрее, но это связано с кешированием, ведь локальные переменные обычно находятся в одной странице памяти, в отличие от глобальных, которые могут быть разбросаны по всему адресному пространству. t00x Вы всегда пишете/читаете локальные переменные через push/pop?
Тогда причём тут влияние ESP на производительность при использовании локальных переменных vs. глобальных? Обычно место под все локальные переменные резервируется одним sub esp,n или несколькими push. В исключительных случаях (жёсткая оптимизация) место вообще не резервируется. Далее чтение/запись осуществляется относительно ESP, EBP или другого регистра. Таким образом, обращение к локальной переменной ничем особо не отличется от обращения к глобальной. А производительность, естественно, может сильно отличаться из-за кеширования.