Trying to use DragDetect() to see if the mouse was dragged, there seem to be two problems with MASM32:
- The function prototype i(in user32.inc) appears to have the wrong # of parameters; the MSDN documentation says two (a window handle and a pointer to a POINT structure), but proto has 3. (Maybe someone thought the function took the X and Y values separately?)
- When I changed the include file, the linker complained it couldn't find it (external symbol name = _DragDetect@8).
Anyone know anything about this?
OK, figured it out.
The C function does take 2 arguments, not 3. Thing is, the 2nd one is a POINT structure which has 2 DWORDs (X and Y). No way to push that on the stack as one parm.
So the assembly-language call is:
INVOKE DragDetect, handle, pt.x, pt.y
The include file is correct after all.
you can look these functions up on MSDN for reference...
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646256%28v=vs.85%29.aspx
all you have to do is "translate" from C to ASM
BOOL WINAPI DragDetect(
__in HWND hwnd,
__in POINT pt
);
INVOKE DragDetect,hwnd,pt
they don't normally show POINT parameters that way - it would usually be a pointer to a POINT structure
in this case, it should be
INVOKE DragDetect,hwnd,x,y
You can do a 1:1 translation like this:
include \masm32\include\masm32rt.inc
MyDragDetect PROTO TheHandle:HWND, ThePoints:POINT
.code
MyPoints POINT <456, 789>
start: invoke MyDragDetect, 123, MyPoints
inkey "ok"
exit
MyDragDetect proc TheHandle:HWND, ThePoints:POINT
print "Px="
print str$(ThePoints.x), 13, 10
print "Py="
print str$(ThePoints.y), 13, 10
ret
MyDragDetect endp
end start
It works, but you can only pass a POINT structure itself, not individual members such as in invoke MyDragDetect, 123, 456, 789
Quote
DragDetect PROTO :DWORD ,:POINT
winuser.sdk
yah - that's how it should be :P
but then you wouldn't be able to use 2 dword parms - you'd always have to combine them
Quote
but then you wouldn't be able to use 2 dword parms - you'd always have to combine them
:naughty:
.data
pt POINT <>
.code
mov pt.x,35
mov pt.y,15
invoke DragDetect,hwnd,pt ;masm accept
no fun if you happen to have X and Y in register
you can do it by pushing the regs and hwnd, then call
it's more fun to...
INVOKE DragDetect,hWin,ecx,edx
:P
actually, i like this function for that, but it is the only one that i have seen
normally, i create the POINT struct on the stack, then pass the pointer in ESP
this saves a PUSH and 2 POP's - lol
Your version works but mine works and is older and shorter :bg
Quote from: jj2007 on October 04, 2011, 11:29:01 AM
MyPoints POINT <456, 789>
start: invoke MyDragDetect, 123, MyPoints
Quote from: ToutEnMasm on October 04, 2011, 05:58:24 PM
.data
pt POINT <>
.code
mov pt.x,35
mov pt.y,15
invoke DragDetect,hwnd,pt ;masm accept
Quote from: ToutEnMasm on October 04, 2011, 05:58:24 PM
Quote
but then you wouldn't be able to use 2 dword parms - you'd always have to combine them
:naughty:
.data
pt POINT <>
.code
mov pt.x,35
mov pt.y,15
invoke DragDetect,hwnd,pt ;masm accept
'MASM accept"? I don't think so. Are you sure?
First problem: too few arguments (the prototype calls for 3).
Second problem: argument type mismatch (it's looking for a DWORD, but you're passing a structure of 2 DWORDs).
Are you using the standard MASM32 include files? Which version of MASM are you using?
I've already determined that
INVOKE DragDetect, handle, pt.X, pt.Y
works correctly, and is apparently what the MASM32 coder intended.
masm will accept it if the prototype is set up that way
Yves (ToutEnMasm) does not use the include files from the masm32 package
The prototype is a problem, but passing a structure on the stack is no problem.
;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================
printf MACRO format:REQ, args:VARARG
IFNB <args>
invoke crt_printf, cfm$(format), args
ELSE
invoke crt_printf, cfm$(format)
ENDIF
EXITM <>
ENDM
;==============================================================================
.data
rect RECT <0,1,2,3>
.code
;==============================================================================
testrc proc rc:RECT
printf( "%d\t%d\t%d\t%d\n\n", rc.left, rc.top, rc.right, rc.bottom )
ret
testrc endp
;==============================================================================
start:
;==============================================================================
invoke testrc, rect
inkey "Press any key to exit..."
exit
;==============================================================================
end start
But it looks like you're passing members (OK, "fields" if you prefer) of the structure, not the whole structure itself.
Regarding Yves' coding, what does his prototype for DragDetect() look like? Is the 2nd parameter a quad word?
well - it is a POINT - not exactly the same as a QWORD, but it's the same size
POINT is a structure definition
in masm, that makes it a type, for all practical purposes
Invoke is passing the whole structure, in "stack-size" chunks and in the correct memory order. Invoke does basically the same thing when passing a REAL8, for example.
Yes; here's what happens 'behind the scenes" (I find it very useful to actually look all the assembler-generated stuff, using the /Fl /Sg options). I created a dummy function "xxx" that takes a POINT as its argument:
xxx proto :POINT
invoke xxx, pt
000002D3 FF 75 FC * push dword ptr ss:[ebp]+0FFFFFFFCh
000002D6 FF 75 F8 * push dword ptr ss:[ebp]+0FFFFFFF8h
000002D9 E8 00000000 E * call xxx
which does exactly what you described.
If you thnk about it, this is just the kind of thing about assembly language that would drive any language purist (like C programmers!) nuts. This seems like the classic ill-defined behavior. Is this even documented anywhere? I haven't seen anything covering this in the MASM manual, f'rinstance.
Anyhow, we know it works, so I guess that's what counts, eh?
Quote from: NoCforMe on October 04, 2011, 08:20:39 PM...the classic ill-defined behavior. Is this even documented anywhere?
Yes, somewhere here in the Forum :bg
Passing a structure is possible but rarely used. As your listing and Olly show, it takes a whopping 12 bytes to pass a global POINT (from my example above):
<ModuleEnt . FF35 04104000 push dword ptr [401004]
0040100E . FF35 00104000 push dword ptr [401000]
Most of the time you have the x & y points in registers anyway - and two push exx takes only two bytes.