This is my first asm project. I probably should have started with
"Hello World" but that's not my style. Part of what I want to do is
display the mouse cursor's coordinates in the window's title bar as
the mouse is moved around the screen. I'm using GetCursorPos to return
pt.x and pt.y. I want to pass those to a procedure that concatenates
a string labelled MCoorStr for display using SetWindowText. Compiling
gives me the following error:
error A2006: undefined symbol : ConcatMCoordStr
I'm guessing I have the wrong data types in the proc declaration or I'm
trying to pass an address rather than a value. Any advice???
Thanks in advance, iaNac
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The pertinant code is as follows...
.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
; Skipped some code
.data
MCoordStr db "X= , Y= ", 0 ; sim. string for window title
MXstr BYTE "X= "
MYstr BYTE "Y= "
; Skipped a bunch of code that displays a window
; and a Message box that when "Yes" is selected
; initiates a timer
; ----------------------------
WndProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
LOCAL var :DWORD
LOCAL caW :DWORD
LOCAL caH :DWORD
LOCAL hdc :HDC
LOCAL ps :PAINTSTRUCT
LOCAL rect :RECT
LOCAL hfont :HFONT
LOCAL pt :POINT
Switch uMsg
Case WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
invoke CreateFont,16,0,0,0,400,0,0,0,OEM_CHARSET ,\
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\
PROOF_QUALITY,DEFAULT_PITCH,\
ADDR FontName
invoke SelectObject, hdc, eax
mov hfont,eax
RGB 0,0,255 ; blue font
invoke SetTextColor,hdc,eax
RGB 255,255,255 ; white font background
invoke SetBkColor,hdc,eax
invoke GetClientRect,hWnd, ADDR rect
invoke DrawText, hdc,ADDR DescrTxt1,-1, ADDR rect, DT_WORDBREAK
invoke EndPaint,hWnd, ADDR ps
Case WM_TIMER
invoke GetCursorPos,ADDR pt ; Get mouse cursor position
;PrintDec pt.x
;PrintDec pt.y
invoke ConcatMCoordStr,MXstr,pt.x,MYstr,pt.y
invoke SetWindowText,hWnd,ADDR MCoordStr
Case WM_COMMAND
Case WM_CREATE
Case WM_SYSCOLORCHANGE
Case WM_SIZE
Case WM_CLOSE
Case WM_DESTROY
invoke PostQuitMessage,NULL
return 0
Endsw
invoke DefWindowProc,hWin,uMsg,wParam,lParam
ret
WndProc endp
; -----------------------
ConcatMCoordStr proc MXtxt:BYTE, ptx:DWORD, MYtxt:BYTE, pty:DWORD
;Concatenation code goes here
ret
ConcatMCoordStr endp
Hi iaNac,
The problem here is that you need to provide a prototype for ConcatMCoordStr. Since it is called before it is defined, the assembler has no way of knowing that it exists, so it says that it doesn't.
In assembly, a prototype is exactly the same at the PROC line, with PROTO substituted for PROC (the variable names are optional, the types aren't).
ConcatMCoordStr proto MXtxt:BYTE, ptx:DWORD, MYtxt:BYTE, pty:DWORD
ConcatMCoordStr proto :BYTE, :DWORD, :BYTE, :DWORD
Also, you appear to want to pass a pointer to MXtxt and MYtxt. Assembly language doesn't require you to specify the underlying type of a pointer (though it is possible), so they should be declared as DWORDs and the parameters in the call should be prefixed with ADDR or OFFSET (OFFSET will not work with local variables while ADDR will generate extra code and destroy whatever is in EAX).
invoke ConcatMCoordStr, ADDR MXstr, pt.x, ADDR MYstr, pt.y
Hopefully this is enough to get you started :thumbu
Cheers,
Zooba :U
Thanks - I'll give it a try!
Hi,
The PROTO should be
ConcatMCoordStr proto :DWORD, :DWORD, :DWORD, :DWORD
and as zooba says you should pass the information by pointer in the function call since the data you have is greater than 1 BYTE
Zooba - Thanks, I'm up and going (stumbling?) again. I had to tweak the invoke a little...
invoke ConcatMCoordStr, MXstr, ADDR pt.x, MYstr, ADDR pt.y
after that, PrintDec ptx gave me the output I was looking for. We'll see if I can concatenate now.
- iaNac
I think you'll find that MXstr and MYstr are the parameters requiring ADDR, since they are strings whihle pt.x and pt.y are DWORD variables.
Would I be right in thinking that you've done C (or similar) programming before? If so, you'll know that strings (char/BYTE arrays) need to be passed by address rather than by value. In this case, you'll have to pass MXstr and MYstr by address and pt.x/y (DWORD/ints) by value.
Just yell if you need any help,
Cheers,
Zooba :U
Thanks, I've never programmed in C. I've done a little API stuff in VB recently and a lot with Pascal before Windows came of age. I've got a lot to learn in asm.
- iaNac
Maybe try
ConcatMCoordStr proc MXtxt:PTR BYTE, ptx:DWORD, MYtxt:PTR BYTE, pty:DWORD
At least when you look at the proto 6 months down the track you can tell PTR BYTE is probably the address of a string.
On another bit, I think using CreateFont in WM_PAINT will create a font every time you get a WM_PAINT (which happens
a fair bit (I think?)) but you're not using DeleteObject to get rid of it when you're finished with it. Better to create it in WM_CREATE,
save the handle in a global DWORD for use by WM_PAINT then delete it in WM_DESTROY (my opinion only).
QuoteI've got a lot to learn in asm.
Haven't we all...that's the fun part.
QuoteThanks, I've never programmed in C. I've done a little API stuff in VB recently and a lot with Pascal before Windows came of age. I've got a lot to learn in asm.
- iaNac
http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/toc.html
Try Art of Assembly book, its riddled with pascal as "pseudo-code" examples, but beware it treats 16 bit assembly wich is not protected mode assembly so you might want to search just for the logic around.