Параметры процедур

Тема в разделе "WASM.BEGINNERS", создана пользователем Zmiy, 11 авг 2007.

  1. Zmiy

    Zmiy New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2007
    Сообщения:
    29
    Объясните, пожалуйста, почему первый код работает, а второй нет:

    (1)

    Код (Text):
    1. WindowProc proc, Window, msg, wParam, lParam: DWORD
    2.  cmp msg, WM_DESTROY
    3.  jne @f
    4.  push 0
    5.  call PostQuitMessage
    6.  @@:
    7.  
    8.  push lParam
    9.  push wParam
    10.  push msg
    11.  push Window
    12.  call DefWindowProc
    13.  ret
    14. WindowProc endp
    (2)

    Код (Text):
    1. .data
    2.  
    3. Window dd 0
    4. msg    dd 0
    5. wParam dd 0
    6. lParam dd 0
    7.  
    8. .code
    9.  
    10. WindowProc proc
    11.  
    12.  mov eax, [ebp + 8]
    13.  mov Window, eax
    14.  mov eax, [ebp + 12]
    15.  mov msg, eax
    16.  mov eax, [ebp + 16]
    17.  mov wParam, eax
    18.  mov eax, [ebp + 20]
    19.  mov lParam, eax
    20.  
    21.  cmp msg, WM_DESTROY
    22.  jne @f
    23.  push 0
    24.  call PostQuitMessage
    25.  @@:
    26.  
    27.  push lParam
    28.  push wParam
    29.  push msg
    30.  push Window
    31.  call DefWindowProc
    32.  ret
    33. WindowProc endp
    Никак не могу понять :dntknw:
     
  2. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Гляди в бинарь, скорее всего причина - ret 10h
     
  3. Zmiy

    Zmiy New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2007
    Сообщения:
    29
    Не работает
     
  4. JAPH

    JAPH New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2007
    Сообщения:
    124
    Пробуем в конце
    Код (Text):
    1. leave
    2. ret 10h
    если не получится, то плюс к этому в начале
    Код (Text):
    1. push ebp
    2. mov ebp, esp
     
  5. Zmiy

    Zmiy New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2007
    Сообщения:
    29
    Большое спасибо! Работает в 2х случаях:

    Код (Text):
    1. WindowProc proc
    2.  push ebp
    3.  mov ebp, esp
    4.  ...
    5.  leave
    6.  ret 0
    7. WindowProc endp
    и

    Код (Text):
    1. WindowProc proc
    2.  push ebp
    3.  mov ebp, esp
    4.  ...
    5.  mov esp, ebp
    6.  pop ebp
    7.  ret 0
    8. WindowProc endp
    (и не нужно никаких 10h). Выходит, что Leave это тоже самое что "mov esp, ebp; pop ebp"?
     
  6. Zmiy

    Zmiy New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2007
    Сообщения:
    29
    А вообще всё работает гораздо проще! :)

    Код (Text):
    1. .data
    2.  
    3. Window dd 0
    4. msg    dd 0
    5. wParam dd 0
    6. lParam dd 0
    7.  
    8. .code
    9.  
    10. WindowProc proc
    11.  pop edx
    12.  pop Window
    13.  pop msg
    14.  pop wParam
    15.  pop lParam
    16.  push edx
    17.  
    18.  cmp msg, WM_DESTROY
    19.  jne @f
    20.  push 0
    21.  call PostQuitMessage
    22.  @@:
    23.  
    24.  push lParam
    25.  push wParam
    26.  push msg
    27.  push Window
    28.  call DefWindowProc
    29.  ret
    30. WindowProc endp
     
  7. AndNot

    AndNot New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2007
    Сообщения:
    49
    Тогда уж еще проще ;)
    Код (Text):
    1. proc WindowProc
    2.     mov    eax,[esp+8]    ; eax - msg
    3.     cmp    eax,WM_DESTROY
    4.     je     @@destroy
    5.     lea    eax,[DefWindowProc]
    6.     jmp    eax
    7. @@destroy:
    8.     push   0
    9.     call   call PostQuitMessage
    10.     ret    10h
    11. endp
     
  8. JAPH

    JAPH New Member

    Публикаций:
    0
    Регистрация:
    23 июн 2007
    Сообщения:
    124
    А чё, параметров не передавалось? Как же Stdcall-конвенция?
    Выходит, что да ;)
     
  9. AndNot

    AndNot New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2007
    Сообщения:
    49
    JAPH, у меня был похожий косяк, тоже забыл поставить очистку стека :) Но поскольку никогда не использую ebp (обращаюсь напрямую через esp), то прога успешно работала несколько суток, после чего благополучно упала :dntknw: Бывает :lol:
     
  10. Zmiy

    Zmiy New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2007
    Сообщения:
    29
    Круто! Наверно надо не один год кодить, чтоб так придумать :)
    Я понял, ret 10h увеличивает esp :) Только непонятно...
    почему так долго? какой тогда размер стэка?
     
  11. AndNot

    AndNot New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2007
    Сообщения:
    49
    Я и начинал еще с убогих советских :)
    А так долго проработала из-за того, что DefWindowProc, в подавляющем большинстве случаев, сам очищал мой стэк, размер которого был минимален :)
     
  12. Zmiy

    Zmiy New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2007
    Сообщения:
    29
    Кстати, ещё один тупой вопрос про стэк
    Правда ли, что работа с переменными в стэке происходит быстрее, чем с глобальными переменными? Если да, то почему?
     
  13. t00x

    t00x New Member

    Публикаций:
    0
    Регистрация:
    15 фев 2007
    Сообщения:
    1.921
    Работа в смысле чтение/запись - pop/push, чем чтение/запись адресацией в память?
     
  14. Zmiy

    Zmiy New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2007
    Сообщения:
    29
    Да
     
  15. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Дада, именно так. Еще есть парная команда ENTER X,X которая заменяет PUSH EBP / MOV EBP,ESP / SUB..., но вроде бы она медленнее, чем push/mov/sub. Так что компиляторы обычно как пролог пишут явно PUSH EBP/MOV EBP,ESP а как эпилог - LEAVE
     
  16. t00x

    t00x New Member

    Публикаций:
    0
    Регистрация:
    15 фев 2007
    Сообщения:
    1.921
    Zmiy
    Одинаково "быстро". pop/push ещё и регистр esp меняют.
     
  17. Zmiy

    Zmiy New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2007
    Сообщения:
    29
    Всем спасибо
     
  18. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Zmiy
    Да, обычно стек работает быстрее, но это связано с кешированием, ведь локальные переменные обычно находятся в одной странице памяти, в отличие от глобальных, которые могут быть разбросаны по всему адресному пространству.

    t00x
    Вы всегда пишете/читаете локальные переменные через push/pop? :)
     
  19. t00x

    t00x New Member

    Публикаций:
    0
    Регистрация:
    15 фев 2007
    Сообщения:
    1.921
    вообще не пользуюсь push/pop непосредственно (invoke разве что).
     
  20. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Тогда причём тут влияние ESP на производительность при использовании локальных переменных vs. глобальных? Обычно место под все локальные переменные резервируется одним sub esp,n или несколькими push. В исключительных случаях (жёсткая оптимизация) место вообще не резервируется. Далее чтение/запись осуществляется относительно ESP, EBP или другого регистра. Таким образом, обращение к локальной переменной ничем особо не отличется от обращения к глобальной. А производительность, естественно, может сильно отличаться из-за кеширования.