Hi, i found a lot of wsprintf topics on the forum and read a few but none of them covered my problem so i opened a new thread and hope thats ok.

Here we go:

I wrote a little program which uses wsprintf and used C calling convention (.model Flat,C)

Thats what the linker gave me

Scrnsize.obj : error LNK2001: unresolved external symbol _ExitProcess
Scrnsize.obj : error LNK2001: unresolved external symbol _GetCommandLineA
Scrnsize.obj : error LNK2001: unresolved external symbol _GetModuleHandleA
Scrnsize.obj : error LNK2001: unresolved external symbol _GetSystemMetrics
Scrnsize.obj : error LNK2001: unresolved external symbol _MessageBoxA

I dont know much about C but it seems to me as if the compiler created some links to several c specific functions, right? (because of the _ infront of the API function names)

After that i tried stdcall instead of c and it works fine now but i dont understand why.

I'm a beginner and i learned that wsprintf has no way to find out how many parameters it gets passed so it can't do the stack handling. Thats why i should use c calling convention which sounds logic but why does it work anyway and what errors do i have to expect in the future if i keep using it with stdcall?
Posted on 2005-07-16 14:55:35 by LittleEndian
The MASM32 includes are written in the assumption that you use STDCALL calling convention, and won't work otherwise. It's a simple fix to make the includes work in other calling conventions, but as usual the fix won't be made. So, use the STDCALL calling convention, and if you need C calling convention some places, add "C" to the function prototype... Or, go through all the MASM32 includes, and add "STDCALL" :)
Posted on 2005-07-16 15:22:29 by f0dder

[...] if you need C calling convention some places, add "C" to the function prototype... [...]


You mean like:

MyFunction PROTO C :DWORD,:DWORD,...? ?

Does that work? The compiler doesnt just regard "C" as a parameter of DWORD type?

If that works, thx for the advice :)

If i missunderstood something then correct me please.


Why does wsprintf work without any C calling convention set? Is the only problem that the parameters given to wsprintf remain on the stack if no1 handles the stackframe and if so why do i have to set C calling convention at all? (in that particular case)? Cant i just handle the stackframe on my own without setting C calling convention? I mean if wsprintf cant handle the stack but the compiler compiles it anyway so it seems to me as if the parameters on the stack just remain unhandled after the function returned and if i set the BP manually back it should be fine, shouldnt it?
Posted on 2005-07-16 16:04:03 by LittleEndian

MyFunction PROTO C :DWORD,:DWORD,...  ?

Does that work? The compiler doesnt just regard "C" as a parameter of DWORD type?

It should - I can't remember the exact syntax (been a while since I used masm, there are other assemblers around), but it seems right. It's something very similar anyway :)

wsprintf is one of the few functions in the MASM32 includes that has it's calling convention set explicitly (because it differs from stdcall), so that should always work. But yes, if it was set to behave as stdcall, you shouldn't have problems unless you do manual push/pop.

Btw, open up windows.inc in your masm32 folder and remove the wsprintf prototype present there, it is in user32.inc and should only be there - otherwise you'll always include user32.dll in your exe no matter if you use it or not.
Posted on 2005-07-16 17:39:12 by f0dder
LittleEndian,

The 5 functions you have listed are STDCALL so calling them using a C or pascal calling convention will not work properly. A C calling convention performs a name change with the leading underscore and does a stack correction after the call, both of which are incorrect under STDCALL.

Now to f0dder who appears to be warming up for another round of personal attacks and abuse, he should in fact know better than to mislead a member of this forum on something as basic as the difference in calling conventione between Windows API calls and a function that has a C calling convention. The MASM32 project correctly prototypes windows API calls as STDCALL with the exception of wsprintfA which is C. It also prototypes the MSVCRT C functions as C calling convention.

If you take incorrect advice from f0dder and modify the include files from MASM32, you can garrantee that your code will not work. Use the standard include files and place the following directive block at the start of your MASM code.


      .486                      ; create 32 bit code
      .model flat, stdcall      ; 32 bit memory model
      option casemap :none      ; case sensitive


Regarding the problem of f0dder and what will be his following responses, this is a matter for the forum moderators.

Regards,

hutch at movsd dot com
Posted on 2005-07-16 17:46:32 by hutch--
(*sigh*)


MASM32 project correctly prototypes windows API calls as STDCALL with the exception of wsprintfA which is C. It also prototypes the MSVCRT C functions as C calling convention.

The MASM32 includes don't prototype the functions, they use the globally defined calling convention, whatever that might be. Not everyone wants to use STDCALL as the global calling convention, and those can't use the includes as-is.


If you take incorrect advice from f0dder and modify the include files from MASM32, you can garrantee that your code will not work. Use the standard include files and place the following directive block at the start of your MASM code.

It might break a few examples that are written with wrong assumptions, but any properly written source code will still build - and you'll get rid of linker warnings as well as a superfluous user32.dll reference.

Posted on 2005-07-16 17:56:06 by f0dder
I actually expect better from you with such a simple difference. You well know that a C calling convention and a STDCALL calling convention handle the name and the stack differently and they don't mix. STDCALL balances the stack at the end of the procedure BEFORE it returns to the caller where a C calling convention procedure simply does a RET and the CALLER balances the stack AFTER the procedure has returned.

With a procedure that has no parameters you can do a direct CALL but with an API call with many arguments like CreateWindowEx() or CreateFont() mixing the calling conventions leaves the application with a serious stack imbalance that can crash the application.

Now as I know where a discussion of this type will end, I ask that the moderators resolve the issue to spare members the usual nonsense.
Posted on 2005-07-16 18:05:13 by hutch--
hutch-, I'm well aware of the differences between C, STDCALL, SYSCALL et cetera - and I know that you are as well, and that you know that I am.

The thing is that the MASM32 includes don't specify any calling convention. Thus, they use whatever calling convention set by the ".model" directive. If a user has chosen ".model flat, C" that would be the default model, and it breaks the masm32 includes. All that is needed is to add the "STDCALL" keyword, and the inculdes would work no matter what.

It's the same reason you have to specify "C" calling convention for wsprintf. It would be better to be explicit and specify the calling convention everywhere, to avoid problems.
Posted on 2005-07-16 19:31:16 by f0dder
There is no problem when you use a system as it is designed, almost exclusively Windows in 32 bit uses STDCALL so it is correct to set a win32 application to,


.model flat, stdcall


Now if someone else wishes to produce their own set of win32 include files for masm, they can do what they like but the complete set of include files that have worked reliably for years require this system and that will never change. Rather than try and modify a very reliable system, simply use it as it was designed. The user who specifies,


.model flat, C


has one default function that will work correctly and will break the rest. At a ratio of over 12000 to 1, there is good reason to set the default to STDCALL and not C.

Now since you are obviously out of date with the current files in MASM32, the 6 bytes that were used with wsprintfA call in the lookup table if that format was used has long since been solved by a conditional assembly block.


IFNDEF _wininc_
  wsprintfA PROTO C :DWORD,:VARARG
  wsprintf equ <wsprintfA>
ENDIF


Under no circumstances should a learner programmer start deleting bits of the WINDOWS.INC file. Giving a learner programmer this type of advice leads to the "error count exceeds 100" problem.
Posted on 2005-07-16 20:12:40 by hutch--

Now if someone else wishes to produce their own set of win32 include files for masm, they can do what they like but the complete set of include files that have worked reliably for years require this system and that will never change. Rather than try and modify a very reliable system, simply use it as it was designed.

What exactly would explicit calling convention specifiers break?


Now since you are obviously out of date with the current files in MASM32, the 6 bytes that were used with wsprintfA call in the lookup table if that format was used has long since been solved by a conditional assembly block.

*shrug* - I just downloaded what seemed like the latest version from the first available mirror. (www.nasn32.com -> download section -> canada nirror of n32v82r.zip). Sorry if that's not recent enough. But good to see you're at least finally doing something to solve the problem :alright:


Under no circumstances should a learner programmer start deleting bits of the WINDOWS.INC file. Giving a learner programmer this type of advice leads to the "error count exceeds 100" problem.

It would solve things that people are asking about here and other places from time to time, and I'm available to help with problems the fix would cause to broken .asm files.
Posted on 2005-07-16 20:28:44 by f0dder


Now if someone else wishes to produce their own set of win32 include files for masm, they can do what they like but the complete set of include files that have worked reliably for years require this system and that will never change. Rather than try and modify a very reliable system, simply use it as it was designed.

What exactly would explicit calling convention specifiers break?


Now since you are obviously out of date with the current files in MASM32, the 6 bytes that were used with wsprintfA call in the lookup table if that format was used has long since been solved by a conditional assembly block.

*shrug* - I just downloaded what seemed like the latest version from the first available mirror. (www.masm32.com -> download section -> canada nirror of m32v82r.zip). Sorry if that's not recent enough. But good to see you're at least finally doing something to solve the problem :alright:


Under no circumstances should a learner programmer start deleting bits of the WINDOWS.INC file. Giving a learner programmer this type of advice leads to the "error count exceeds 100" problem.

It would solve things that people are asking about here and other places from time to time, and I'm available to help with problems the fix would cause to broken .asm files.


<edit> - darn those "natural keyboard" are alien when you're not used to them! - hope I caught all the typos
Posted on 2005-07-16 20:29:54 by f0dder
Yeah,

I wondered what had happened with the duplicate quote.

Here is a quick sample of the consequences of a learner taking your advice and willy nilly changing the design of the system. the system is designed for the standard windows calling convention (STDCALL), change it to C and you get this.


appath.obj : error LNK2001: unresolved external symbol _dwtoa
appath.obj : error LNK2001: unresolved external symbol _WordCount
appath.obj : error LNK2001: unresolved external symbol _szLen
appath.obj : error LNK2001: unresolved external symbol _szLower
appath.obj : error LNK2001: unresolved external symbol _szRemove
appath.obj : error LNK2001: unresolved external symbol _GetAppPath
appath.obj : error LNK2001: unresolved external symbol _GetStockObject
appath.obj : error LNK2001: unresolved external symbol _BeginPaint
appath.obj : error LNK2001: unresolved external symbol _DialogBoxIndirectParamA
appath.obj : error LNK2001: unresolved external symbol _DrawEdge
appath.obj : error LNK2001: unresolved external symbol _EndDialog
appath.obj : error LNK2001: unresolved external symbol _EndPaint
appath.obj : error LNK2001: unresolved external symbol _GetActiveWindow
appath.obj : error LNK2001: unresolved external symbol _GetClientRect
appath.obj : error LNK2001: unresolved external symbol _GetDlgItem
appath.obj : error LNK2001: unresolved external symbol _GetWindowRect
appath.obj : error LNK2001: unresolved external symbol _LoadIconA
appath.obj : error LNK2001: unresolved external symbol _MessageBoxA
appath.obj : error LNK2001: unresolved external symbol _SendMessageA
appath.obj : error LNK2001: unresolved external symbol _SetWindowTextA
appath.obj : error LNK2001: unresolved external symbol _ExitProcess
appath.obj : error LNK2001: unresolved external symbol _GetModuleHandleA
appath.obj : error LNK2001: unresolved external symbol _GlobalAlloc
appath.obj : error LNK2001: unresolved external symbol _GlobalFree
appath.obj : error LNK2001: unresolved external symbol _MultiByteToWideChar
appath.obj : error LNK2001: unresolved external symbol _InitCommonControls
appath.exe : fatal error LNK1120: 26 unresolved externals


Mess around with the include files and windows.inc and you risk,


fatal error A1012: error count exceeds 100; stopping assembly


Now with a ratio in excess of 12000 to 1, is there some point in explicitly setting every STDCALL prototype to STDCALL when the standard notation,


.model flat, stdcall


Automatically sets the calling convention to the windows standard. Even if you add the 730 MSVCRT functions to the list, its still greater than 10 to 1 so there is no point in placing C calling convention procedures on the same level as system based STDCALL.

Now if someone want to do so, there is nothing stopping them from creating their own set of include files but I will not support alternative systems in the MASM32 project and anyone who wants to use such alternatives will need to get their support from the author of such an alternative.


It would solve things that people are asking about here and other places from time to time, and I'm available to help with problems the fix would cause to broken .asm files.


The simplest response is to give them the right advice in the first place, not mislead them. Set up the source file according to the existing system as follows.


      .486                      ; create 32 bit code
      .model flat, stdcall      ; 32 bit memory model
      option casemap :none      ; case sensitive


There is no common method in building these files in MASM, use a different system, get your support somewhere else.

I don't see that this discussion will lead to anything else than it always has and I see that the members should be spared nonsense of this type.

This is a matter where the forum moderators should step in to prevent members from being mislead.
Posted on 2005-07-16 20:47:23 by hutch--

the system is designed for the standard windows calling convention (STDCALL), change it to C and you get this.

Which is the problem of the origina poster, and what I commented on. The solution is to change all the prototypes in the include files to include the STDCALL specifier where necessary, so you remove the dependency on the .model specifiet.


Mess around with the include files and windows.inc and you risk,

Adding STDCALL to the protos will rid you of problems when people have another default calling convention, and removing the wsprintf proto from windows.inc will remove a linker warning as well as a an unnecessary dll file inclusion (but if your header inclusion guard fixes it, more power to that).


Now with a ratio in excess of 12000 to 1, is there some point in explicitly setting every STDCALL prototype to STDCALL when the standard notation,

Or fix the MASM32 includes. I know what outrage it would cause if microsoft hadn't specified calling convention or parameter types for their APIs :)

Sure, fixing the masm32 includes would make the files a bit larger - but it wouldn't be a problem for distribution size (solid compression and/or a inc-file-generator would fix that), and as for compile speed, Randall Hyde has already demonstrated that masm is more than fast enough.


This is a matter where the forum moderators should step in to prevent members from being mislead.

That's up for the forum moderators to decide. If you're not happy with them, moderate your own forum.




Posted on 2005-07-16 21:37:45 by f0dder
Hutch,

I stand by f0dder's argument. It sound to me, but I guess you don't see the validity of his argument and refuses to follow his advice. But it is wrong for you to claim that he mislead people because he clearly did not do so.

All I have seen through out these years is that you have been provoking f0dder like for instance asking him to publish his own library and so on. These are not appropriate behaviour.

To Everyone:
I'm sick of seeing these kind of threads on this forum so I'm locking it.
Posted on 2005-07-17 10:57:14 by roticv