|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Апр 3, 2004 16:47:54 Не секрет что использование макросов типа .IF/.ELSEIF/.ELSE/.ENDIF в обработчике сообщений диалогового окна приводит к некрасивому коду, но вот использование case/switch в C или CASE/OF в Delphi вполне с этим справляется, код получается правильный без глупых прыжков типа: jnz @F ...... @@: jmp @F ...... @@: xor eax, eax inc eax ret Т.е. вместо того чтобы сразу прыгнуть на последнюю метку оно прыгает через промежуточный jmp Есть ли какие-нибудь удачные попытки сделать макросы типа case/switch в masm32, может в fasm? |
|
|
Дата: Апр 3, 2004 17:48:31 · Поправил: S_T_A_S_ Я макросы не писал, делаю табличку (по 6 байт на сообщ. но можно и меньше) И юзаю примерно такой код (он один для всех окон):
macro MSGH message, handler
{ dw meesage
dd handler }
;; создаем табличку:
MsgHandles:
MSGH WM_PAINT,Window.WM_PAINT
MSGH WM_CREATE,Window.WM_CREATE
MSGH WM_WINDOWPOSCHANGING,Window.SetClientSize
dw WM_NULL ;; end of MSGH table
;; обрабатываем сообщ.
movzx edx, WORD[uMsg] ;; MS allows to use only WORD
mov eax, MsgHandles ;; message table
@@: movzx ecx, WORD[eax+0] ;; get element from table
add eax, 6 ;; next table element
or ecx, ecx ;; if zero, the end. process default
je .WM_NULL
cmp ecx, edx ;; check message
jne @b ;; not our message
call [eax+2-6] ;; call msg_handler
;; predefined message handlers
.WM_NULL:
jmp [DefWindowProc]
|
|
|
Дата: Апр 3, 2004 18:12:00 · Поправил: Asterix Ага, работаешь как оптимизирующий компилятор MSVC или Delphi, там тоже такое в начале, и идут условные джампы в нужные места, но мысль я понял, надо будет попробовать сделать подобное для диалогового окна, которое из шаблона в rc, хотя есть у меня и другие мысли как немного улучшить код при использовании .IF/.ENDIF не прибегая к переходу на чистый asm. |
|
|
Дата: Апр 3, 2004 18:40:47 А что нельза что ли написать так mov eax, uMsg cmp eax, WM_PAINT jnz @@1 ... cmp eax, WM_COMMAND jnz @@2 ... Ведь чаще всего к окну приходят сообщения WM_PAINT, потом WM_COMMAND, а остальные изредка, зачем тогда эти таблицы? |
|
|
Дата: Апр 3, 2004 18:57:48 Я вот такое пользую собственного изготовления (скорее для наглядности, чем ради оптимизации). IF_MSG MACRO msg:REQ, do:REQ
cmp eax, msg
jz do
ENDM
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::
Wnd_OnDestroy proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
option PROLOGUE:NONE
option EPILOGUE:NONE
WND_PROC_LOCAL dwLocal1:DWORD, dwLocal2:DWORD
invoke PostQuitMessage, 0
pop eax
jmp eax ; jmp LeaveWndProc
option PROLOGUE:PROLOGUEDEF
option EPILOGUE:EPILOGUEDEF
Wnd_OnDestroy endp
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
WND_PROC_LOCAL
push LeaveWndProc0
mov eax, uMsg
IF_MSG WM_CREATE, Wnd_OnCreate
IF_MSG WM_DESTROY, Wnd_OnDestroy
pop eax
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
LeaveWndProc0::
xor eax, eax ; return FALSE
LeaveWndProc::
ret
WndProc endp
Про switch/case ищи тут http://board.win32asmcommunity.net/ темы "What is impossible?Optimized switch/case? NOT!" "Optimizing Switch/Case..." И, кстати, тема организации цикла обработки сообщений там тоже измусолена основательно. |
|
|
Дата: Апр 3, 2004 19:29:41 · Поправил: S_T_A_S_ Asterix Тут же нет условных джампов (почти) :-? [ dragon - зачем тогда эти таблицы? ] Экономия памяти Кроме того, если это немного модернизировать - хранить смещение адреса обработчика (2 байта) вместо адреса, то можно экономить еще по 2 байта на сообщении (Delphi ?) :-) Самое главное в таком подходе - можно наделать кучу таблиц для разных окошек, а обрабатывать будет один и тот же код. Тот же код может обрабатывать и еще что-то, например нажатые клавиши. Это старинный трюк, который сейчас широко используется в т.н. "ООП" :D |
|
|
Дата: Апр 3, 2004 20:33:10 [ dragon: А что нельза что ли написать так] Иногда так и пишу, но я же написал что не хотелось бы переходить в данном случае на чистый асм, здесь это не требуется, зачем забивать код лишними cmp/jz/jnz. |
|
|
Дата: Апр 3, 2004 21:03:00 Asterix Ну не знаю, я так вообще никогда не использую всякие .IF, .ELSE и др, если уж асм так асм и никаких высокоуровневых конструкций. Одно дело - макросы типа CCOUNTED_UNICODE_STRING(для строк UNICODE_STRING) а другое - это такие конструкции, к тому же они скрывают часть кода. |
|
|
Дата: Апр 3, 2004 21:05:30 > к тому же они скрывают часть кода. Не настолько значимую чтоб не скрывать ;-) |
|
|
Дата: Апр 4, 2004 01:05:50 В проекте Fresh я изпользую вот что:
macro MessageList [message, msghandler] {
forward
dw message,msghandler - $ - 2
common
dd 0
}
;------------------------------------------------------
; proc JumpTo
; Searches for the message in the message table.
; Arguments:
; ebx - message number to search in the table.
; Returns:
; This procedure doesn't returns. It simply
; jumps to the address from table or imediately
; after the table if the message is not found.
; in both cases esi = eip
; Uses:
; eax, esi
;------------------------------------------------------
proc JumpTo
begin
pop esi ; get table address and remove return
; address from the stack.
.loop:
lodsd
test eax,eax
jz .exit
cmp bx, ax
jne .loop
sar eax, 16
add esi, eax
.exit:
jmp esi
endp
А изпользуеться вот так:
mov ebx, [wmsg] ; ето собственно message
call JumpTo
MessageList \
WM_INITDIALOG, .wminitdialog, \
WM_??????, .???, \
WM_NOTIFY, .wmnotify
|
|
|
Дата: Апр 4, 2004 02:09:29 JMP на метку медленнее чем просто 'провалиться' дальше по коду. Так что вот это: cmp eax, WM_xxx je @@_1 cmp eax, WM_xxx je @@_2 cmp eax, WM_xxx je @@_3 лучше чем вот это: cmp eax, WM_xxx jne @@_chk_2 ; handler #1 ... @@_chk_2: cmp eax, WM_xxx jne @@_chk_3 ; handler #2 ... @@_chk_3: cmp eax, WM_xxx jne @@_chk_4 ; handler #3 ... но наверное, лучший метод - через таблицу (как S_T_A_S_). Кстати, в библиотеке AsmDev32 будет такой объект - динамический линейный вектор, который строится добавляя 32-битное значение и адрес обработчика. Далее, вызываем метод Route и происходит поиск значения и вызов обработчика. Там ещё передаётся LPARAM для самой функции обработчика (для универсальности - в Windows везде так). Кроме того, есть сортировка по значениям и бинарный поиск (если надо). В общем, наворочено... Я понимаю, что это не самый эффективный подход, но чтобы получить что-то работающее - в самый раз, а оптимизировать надо после отладки. |
|
|
Дата: Апр 4, 2004 17:44:28 · Поправил: Asterix Суммировав всё вышесказанное, а также прочтенное на board.win32asmcommunity.net для себя я остановился на таком макросе увиденном у The Svin'а: WM_CASE MACRO reg:REQ, msgs:REQ
IRP msg, <msgs>
cmp reg, WM_&msg
je @&msg
ENDM
ENDM
Применять так: DlgProc proc hWnd, uMsg, wParam, lParam mov eax, uMsg WM_CASE eax, <INITDIALOG, COMMAND, CLOSE> @r0: xor eax, eax ret @INITDIALOG: ....................... jmp @r1 @COMMAND: mov eax, wParam ....................... jmp @r1 @CLOSE: invoke EndDialog, hWnd, 0 @r1: xor eax, eax inc eax ret DlgProc endp |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.075 |