The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: bf2 on November 03, 2011, 04:47:32 PM

Title: Confused with wsprintf
Post by: bf2 on November 03, 2011, 04:47:32 PM
The file masm32\m32lib\dw2a.asm has the following prototype of wsprintf:

wsprintfA PROTO C :DWORD,:VARARG

Windows.inc on the other hand has the prototype:

wsprintfA PROTO C :VARARG

Finally, MSDN has the definition:

int __cdecl wsprintf(
  __out  LPTSTR lpOut,
  __in   LPCTSTR lpFmt,
  __in    ...
);


Question 1a. Which of the above is correct? I am sure the answer is 'all of them', but how?

Question 1b. Regarding the '... [in]' bit, MSDN says the following:
"One or more optional arguments. The number and type of argument parameters depend on the corresponding format-control specifications in the lpFmt parameter."
What on earth might that mean? Can anyone provide an example?

Question 2: How do the following calls work? How does wsprintf work out what parameter is at what possition?
Example 1: MASM

invoke wsprintf, lpBuffer, ADDR formatString, dwValue


Example 2: C

wsprintf (szBuffer, "The sum of %i and %i is %i", 5, 4, 5 + 4);


In other words, in the first case we are passing the format string as a separate parameter, while in the second it's included in the second parameter !

Thanks as always.
Title: Re: Confused with wsprintf
Post by: qWord on November 03, 2011, 05:04:01 PM
formal correct:
wsprintfA proto c :LPTSTR, :LPCTSTR, args:VARARG
:bg
However, because of VARAGR, the other definitions will also work (as long as passing the buffer and the format-string)
Title: Re: Confused with wsprintf
Post by: qWord on November 03, 2011, 05:16:45 PM
Quote from: bf2 on November 03, 2011, 04:47:32 PMWhat on earth might that mean? Can anyone provide an example?

Question 2: How do the following calls work? How does wsprintf work out what parameter is at what possition?

Quote"The sum of %i and %i is %i", 5, 4, 5 + 4
Title: Re: Confused with wsprintf
Post by: bf2 on November 03, 2011, 05:28:17 PM
Quote from: qWord on November 03, 2011, 05:16:45 PM
Quote from: bf2 on November 03, 2011, 04:47:32 PMWhat on earth might that mean? Can anyone provide an example?

Question 2: How do the following calls work? How does wsprintf work out what parameter is at what possition?

Quote"The sum of %i and %i is %i", 5, 4, 5 + 4

I understand that, but how does that fit with the prototype? And how can in another call we can pass th format string as an entirely separate parameter?
Title: Re: Confused with wsprintf
Post by: qWord on November 03, 2011, 06:36:12 PM
Quote from: bf2 on November 03, 2011, 05:28:17 PMI understand that, but how does that fit with the prototype? And how can in another call we can pass th format string as an entirely separate parameter?
Beacause the created code is the same for all variations -> you can declare each c-function with VARARG as long as  using the right number of parameters when calling the function (the types must also match).

Calling conventions (pdf) (http://www.agner.org/optimize/calling_conventions.pdf)
Title: Re: Confused with wsprintf
Post by: NoCforMe on November 03, 2011, 07:00:15 PM
My take on this--and I really don't want to confuse things further with wrong information, so please correct me if I'm wrong---is that the MSDN definition is the best one. wsprintf() takes 2 mandatory arguments (the output buffer and the format string), and a variable number of arguments (0-n) after that.

I don't understand why the windows.inc file only lists the variable-argument list: isn't that incorrect? Seems to me that the prototype should have at least 2 DWORDs followed by the VARARG. Why is that?
Title: Re: Confused with wsprintf
Post by: bf2 on November 03, 2011, 07:30:31 PM
Quote from: NoCforMe on November 03, 2011, 07:00:15 PM
My take on this--and I really don't want to confuse things further with wrong information, so please correct me if I'm wrong---is that the MSDN definition is the best one. wsprintf() takes 2 mandatory arguments (the output buffer and the format string), and a variable number of arguments (0-n) after that.

I don't understand why the windows.inc file only lists the variable-argument list: isn't that incorrect? Seems to me that the prototype should have at least 2 DWORDs followed by the VARARG. Why is that?

NoCforMe, you are right that things are very confusing (well for me anyway). For example even if we take the MSDN definition to be the correct one, how then can a C call like the below work?
wsprintf (szBuffer, "The sum of %i and %i is %i", 5, 4, 5 + 4);
Because as per the MSDN definition, the format string must be the second parameter passed, whereas the call passes an arbitrary string with the format string embedded in it.

Edit. OK, I got that bit. The MSDN description says about the second parameter:
"    [in] Pointer to a null-terminated string that contains the format-control specifications. In addition to ordinary ASCII characters, a format specification for each argument appears in this string."
So the second parameter can be an arbitrary string containing the format string, or just the format string.
Title: Re: Confused with wsprintf
Post by: jj2007 on November 03, 2011, 07:37:59 PM
Here is a little testbed. Attached the disassembly.
The point here is that TestOnePlusVar and TestVarArg behave identically, unless you insist to call TestOnePlusVar without any args.

include \masm32\include\masm32rt.inc

TestFix PROTO :DWORD, :DWORD
TestFixC PROTO C :DWORD, :DWORD
TestOnePlusVar PROTO C :DWORD, :VARARG
TestVarArg PROTO C :VARARG

.code
start: inkey "bye"
exit
invoke TestFix, 1, 2
invoke TestFixC, 1, 2
; invoke TestOnePlusVar ; error A2137:too few arguments to INVOKE
invoke TestVarArg
invoke TestOnePlusVar, 1
invoke TestVarArg, 1
invoke TestOnePlusVar, 1, 2, 3
invoke TestVarArg, 1, 2, 3

TestFix proc v1, v2
  mov eax, v1
  mov ecx, v2
  ret
TestFix endp

TestFixC proc C v1, v2
  mov eax, v1
  mov ecx, v2
  ret
TestFixC endp

TestOnePlusVar proc C v1, v2:VARARG
  mov eax, v1
  mov ecx, v2
  ret
TestOnePlusVar endp

TestVarArg proc C v1:VARARG
  mov eax, v1
  ret
TestVarArg endp

end start
Title: Re: Confused with wsprintf
Post by: NoCforMe on November 03, 2011, 09:16:32 PM
Quote from: bf2 on November 03, 2011, 07:30:31 PM
Edit. OK, I got that bit. The MSDN description says about the second parameter:
"    [in] Pointer to a null-terminated string that contains the format-control specifications. In addition to ordinary ASCII characters, a format specification for each argument appears in this string."
So the second parameter can be an arbitrary string containing the format string, or just the format string.

Wellll ... the second argument is always the format string (dunno what you mean by "arbitrary" there).

Forget MASM, or assembly language in general: this all stems from the classic C definition of xxprintf(). The "format" string is just that: a string that controls the formatting of the output. In what mathematicians would call the "degenerate case", the format string itself can be the output, as in



wsprintf (&buffer, "This is all she wrote");



(here the number of variable args is zero) Does that make sense?

(To put this another way, the number of arguments after the two required ones depends on the content of the formatting string, where each replacement field found (%(something)) requires a parameter to fill that field.)

In any case, two arguments are definitely required by this function, so I still am confused as to the windows.inc prototype, despite jj's attempt at elucidation.
Title: Re: Confused with wsprintf
Post by: bf2 on November 03, 2011, 10:00:28 PM
Quote from: NoCforMe on November 03, 2011, 09:16:32 PM
Quote from: bf2 on November 03, 2011, 07:30:31 PM
Edit. OK, I got that bit. The MSDN description says about the second parameter:
"    [in] Pointer to a null-terminated string that contains the format-control specifications. In addition to ordinary ASCII characters, a format specification for each argument appears in this string."
So the second parameter can be an arbitrary string containing the format string, or just the format string.

Wellll ... the second argument is always the format string (dunno what you mean by "arbitrary" there).


Ignore me. I got myself confused by the example where the second parameter is a string like "The number is %ld" as opposed to just "%ld".
I am easily confused.
Title: Re: Confused with wsprintf
Post by: NoCforMe on November 03, 2011, 10:07:52 PM
Don't worry, you ain't the only one. Join the club.

Hey, you know what's a great antidote to your confusion? Write your own version of wsprintf().

Seriously. I don't mean a full-blown implementation, with all the bells and whistles and formats. I wrote my own version of printf() (back in my 16-bit coding days) that handles the following data types:

It's actually not all that hard, and is a good programming exercise. If you do it, you'll really "get" the whole format string business.