The MASM Forum Archive 2004 to 2012

Project Support Forums => IDE Development and Support => Easy Code => Topic started by: BPak on April 24, 2008, 12:58:32 AM

Title: WSPRINTF causes error ?
Post by: BPak on April 24, 2008, 12:58:32 AM
The wsprintf  function gives me an error when closing the Message box.

I must be missing something in using the WSPRINTF.

Any help appreciated!

.Const

.Data

MESSAGES DD WM_CREATE, OnCreate
DD WM_CLOSE, OnClose
DD WM_COMMAND, OnClickBtn

sCap DB 'Screen Size', 0

.Code

winMainProcedure Frame hWnd, uMsg, wParam, lParam
Mov Eax, [uMsg]
Mov Ecx, SizeOf MESSAGES / 8
Mov Edx, Addr MESSAGES
: Dec Ecx
Js >L2
Cmp [Edx + Ecx * 8], Eax
Jne <
Call [Edx + Ecx * 8 + 4]
Ret
L2: Return (FALSE)
EndF

OnCreate:
UseData winMainProcedure
;==================================
;Write the initialization code here
;==================================
Return (TRUE)
EndU

OnClose:
UseData winMainProcedure
;=========================
;Write the final code here
;=========================
Invoke IsModal, [hWnd]
Or Eax, Eax ;Cmp Eax, FALSE
Jz >
Invoke EndModal, [hWnd], IDCANCEL
Mov Eax, TRUE ;Return (TRUE)
: Ret
EndU
OnClickBtn:
UseData winMainProcedure
    Local sbuf[64]:B, cxScreen:D, cyScreen:D

Mov Eax, [wParam]
Cmp Ax, IDC_WINMAIN_BTNSCREEN
Jnz >>.exitProcedure

Shr Eax, 16
Cmp Ax, BN_CLICKED
Jnz >>.exitProcedure

    Invoke GetSystemMetrics, SM_CXSCREEN
    Mov [cxScreen], Eax

    Invoke GetSystemMetrics, SM_CYSCREEN
    Mov [cyScreen], Eax

    Invoke wsprintf, Addr sbuf, "The screen is %d pixels wide by %d pixels high.", \
     [cxScreen], [cyScreen]

    Invoke MessageBox, NULL, Addr sbuf, Addr sCap, 0

Return (TRUE)

.exitProcedure
Return (FALSE)     
EndU


BPak
Title: Re: WSPRINTF causes error ?
Post by: Ramon Sala on April 24, 2008, 06:44:04 AM
Hi BPak,

In the MSDN library there is the following note:

Note: It is important to note that wsprintf uses the C calling convention (_cdecl), rather than the standard call (_stdcall) calling convention. As a result, it is the responsibility of the calling process to pop arguments off the stack, and arguments are pushed on the stack from right to left. In C-language modules, the C compiler performs this task.


High level languages and also Masm restore the stack but GoAsm does not, so you have to accomplish this task after calling wsprintf. In your code, as you pass four DWord arguments (that is, 4-byte each) to wsprintf, you have to add 16 bytes (4*4) to the Esp register like this:

    ....
    Invoke wsprintf, Addr sbuf, "The screen is %d pixels wide by %d pixels high.", \
               [cxScreen], [cyScreen]
    Add Esp, 16
    Invoke MessageBox, NULL, Addr sbuf, Addr sCap, 0
    ....



That's all!

Ramon
Title: Re: WSPRINTF causes error ?
Post by: BPak on April 24, 2008, 09:39:42 PM
Hi Ramon,

Quoteuses the C calling convention (_cdecl),

Thanks for the solution.  I will put that in my notes and keep look out for those _cdecl functions!

Working fine now!

BPak
Title: Re: WSPRINTF causes error ?
Post by: Vortex on April 24, 2008, 09:51:52 PM
BPak,

Donkey coded a macro to call C functions, it takes care of stack balancing :

CInvoke(%Function,%0,%1,%2,%3,%4,%5,%6,%7,%8,%9) MACRO
#IF ARGCOUNT = 11
push %9
#ENDIF
#IF ARGCOUNT > 9
push %8
#ENDIF
#IF ARGCOUNT > 8
push %7
#ENDIF
#IF ARGCOUNT > 7
push %6
#ENDIF
#IF ARGCOUNT > 6
push %5
#ENDIF
#IF ARGCOUNT > 5
push %4
#ENDIF
#IF ARGCOUNT > 4
push %3
#ENDIF
#IF ARGCOUNT > 3
push %2
#ENDIF
#IF ARGCOUNT > 2
push %1
#ENDIF
#IF ARGCOUNT > 1
push %0
#ENDIF
call %Function
#IF ARGCOUNT = 11
add esp,40
#ENDIF
#IF ARGCOUNT = 10
add esp,36
#ENDIF
#IF ARGCOUNT = 9
add esp,32
#ENDIF
#IF ARGCOUNT = 8
add esp,28
#ENDIF
#IF ARGCOUNT = 7
add esp,24
#ENDIF
#IF ARGCOUNT = 6
add esp,20
#ENDIF
#IF ARGCOUNT = 5
add esp,16
#ENDIF
#IF ARGCOUNT = 4
add esp,12
#ENDIF
#IF ARGCOUNT = 3
add esp,8
#ENDIF
#IF ARGCOUNT = 2
add esp,4
#ENDIF
ENDM


GoAsm header file set and macros by Donkey :

http://www.quickersoft.com/donkey/headers/headers.zip