Some Windows messages (e.g. WM_MOUSEMOVE) give x, y coordinates in lParam. To be used, they must be converted by ScreenToClient, the latter expecting a POINT structure. I have been playing with some alternatives and wonder whether anybody knows better ones, in terms of size (speed can be neglected for this kind of messages).
xx proc .... lParam:DWORD
LOCAL pt:POINT
movzx eax, word ptr lParam ; 7
; mov pt.x, eax
mov eax, lParam ; 6
sar eax, 16 ; 3 ->7+6+3=16 bytes
; mov pt.y, eax
movzx eax, word ptr lParam ; 7
; mov pt.x, eax
movzx eax, word ptr lParam+2 ; 7 ->7+7=14 bytes
; mov pt.y, eax
mov eax, lParam ; 6
mov ecx, eax ; 2
sar ecx, 16 ; 3
; mov pt.y, ecx
cwde ; 1 ->6+2+3+1=12 bytes
; mov pt.x, eax
mov eax, lParam ; 6
push eax ; 1
sar eax, 16 ; 3
; mov pt.y, eax
pop eax ; 1
cwde ; 1 ->6+1+3+1+1=12 bytes
; mov pt.x, eax
For a start, you could replace:
mov eax,dword ptr [lParam]
sar eax,16
with
movsx eax,word ptr [lParam+2]
Sometimes movsx is wrong solution if word-size parameter must be treated as unsigned - movzx is right.
But in this case movsx is right. (in the case of receiving mouse-coordinates - they will be negative when you drag).
Also, WM_MOUSE messages don't make you use ScreenToClient. The only proc to make you use ScreenToClient is GetCursorPos. So, you don't actually need to put x:y into a POINT.
Quote from: Ultrano on April 03, 2008, 12:34:04 PM
But in this case movsx is right
Thanx, I had overlooked that.
Quote
Also, WM_MOUSE messages don't make you use ScreenToClient. The only proc to make you use ScreenToClient is GetCursorPos. So, you don't actually need to put x:y into a POINT.
I checked, and it's correct for WM_MOUSEMOVE, but not for WM_NCMOUSEMOVE (I use the latter...).
Thanx to all of you.
Hi,
are you sure that you've got those calculations correct? Here's what I get when I disassemble that (with the totals after the lines) - the top two are the movements to the POINT structure for both local and globals:
:00401024 A314304000 mov dword ptr [00403014], eax ; 5 (Global)
:00401029 8945F8 mov dword ptr [ebp-08], eax ; 3 (Local)
:0040102C 0FB74510 movzx eax, word ptr [ebp+10] ; 4 +
:00401030 8B4510 mov eax, dword ptr [ebp+10] ; 3 +
:00401033 C1F810 sar eax, 10 ; 3 = 10
:00401036 0FB74510 movzx eax, word ptr [ebp+10] ; 4 +
:0040103A 0FB74512 movzx eax, word ptr [ebp+12] ; 4 = 8
:0040103E 8B4510 mov eax, dword ptr [ebp+10] ; 3 +
:00401041 8BC8 mov ecx, eax ; 2 +
:00401043 C1F910 sar ecx, 10 ; 3 +
:00401046 98 cwde ; 1 = 9
:00401047 8B4510 mov eax, dword ptr [ebp+10] ; 3 +
:0040104A 50 push eax ; 1 +
:0040104B C1F810 sar eax, 10 ; 3 +
:0040104E 58 pop eax ; 1 +
:0040104F 98 cwde ; 1 = 9
Your totals would be correct if lParam were a global, but I assume that it will be a parameter to the procedure in your code.
Ossa
[edit] No, I think that they'd still be wrong actually [/edit]
I am afraid you are right, and I am wrong! I had tested "lParam" in a box, and assumed it would not make a difference if it was an argument or a local variable. In fact, it makes a big difference:
00404D87 |. 0FB785 B0FCFFF>MOVZX EAX,WORD PTR SS:[EBP-350] lParam as LOCAL
00404D8E |. 0FB785 B2FCFFF>MOVZX EAX,WORD PTR SS:[EBP-34E] 7+7=14
00404D97 |. 0FBF45 0C MOVSX EAX,WORD PTR SS:[EBP+C] lParam as argument
00404D9B |. 0FBF45 0E MOVSX EAX,WORD PTR SS:[EBP+E] 4+4=8
I keep learning - thanks a lot!