The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: cork on July 20, 2010, 09:07:32 AM

Title: wsprintf
Post by: cork on July 20, 2010, 09:07:32 AM
I've included a MASM32 source file, below, with an example.

I'm using 64-bit Windows Vista and MASM32 to assemble.

I pass a QWORD to wsprintf using the '%lu' format specifier. Instead of translating the entire 64-bit unsigned integer into an ASCII string, it translates only the low 32-bits, altogether ignoring the high 32-bits.

In the example below the ASCII string that wsprintf returns is "3" (just the low 32-bits). It should return "4294967299".

I've spent the past hour trying to suss out the issue. Any insights into what kind of bonehead assumption I've made that isn't correct?


.486                          ; For 80486 CPUs or higher.
.model flat, stdcall        ; Windows is always the 32-bit FLAT model
option casemap:none    ; Use case-sensitive labels.

include    \masm32\include\windows.inc       ; always first
include    \masm32\include\kernel32.inc     
includelib \masm32\lib\kernel32.lib
include    \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

.data

MsgTitle       db  '64-bit Unsigned', 0
MsgText       db  '                                                ', 0
blah            dq  4294967299   ; [addr]=low dword=03H, [addr+4]=high dword=01H
lu_format     db  '%lu', 0

.code

Test1:
    invoke wsprintf, addr MsgText, OFFSET lu_format, blah
    invoke  MessageBox, 0, ADDR MsgText, ADDR MsgTitle, MB_OK or MB_ICONINFORMATION
exit_Test1:
    invoke ExitProcess, 0
    ret
end Test1
Title: Re: wsprintf
Post by: MichaelW on July 20, 2010, 10:06:55 AM
The wsprintf function apparently does not support 64-bit integers. You can use the CRT sprintf function instead (build this example as a console app).

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      msgtext   db 20 dup(0)
      i64       dq 1234567887654321h
      format    db "%I64x", 0
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke crt_sprintf, ADDR msgtext, ADDR format, i64
    print ADDR msgtext,"h",13,10,13,10

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

Title: Re: wsprintf
Post by: cork on July 20, 2010, 10:11:43 AM
Maybe %u and %lu are equivalent specifiers, both meaning an unsigned 32-bit integer.

That must be the case.

I guess if I'm going to translate a 64-bit unsigned integer to a string I have to do it myself, as it doesn't look wsprintf() supports it.

Title: Re: wsprintf
Post by: MichaelW on July 20, 2010, 10:38:42 AM
I'm fairly certain that wsprintf was, at least originally, based on the CRT sprintf function. For C (32-bit, not the old 16-bit versions) int and long int are both 32-bit integers, so the "l" (long) modifier specifies a 32-bit integer and "%u" and "%lu" are effectively the same. To specify a 64-bit integer you would need to use "ll" (long long), except for the Microsoft C's where you would need to use "I64", but note that wsprintf apparently supports neither. And since it also does not support floating-point values, I basically see no reason to use wsprintf for anything.
Title: Re: wsprintf
Post by: MichaelW on July 20, 2010, 10:57:06 AM
According to  this (http://msdn.microsoft.com/en-us/library/ms647550(v=VS.85).aspx), "Starting with Windows XP, wsprintf and wvsprintf support the I64|I modifiers."
Title: Re: wsprintf
Post by: cork on July 20, 2010, 11:11:24 AM
Quote from: MichaelW on July 20, 2010, 10:57:06 AM
According to  this (http://msdn.microsoft.com/en-us/library/ms647550(v=VS.85).aspx), "Starting with Windows XP, wsprintf and wvsprintf support the I64|I modifiers."

Thank you very much Michael. That works perfectly.

'%I64d' for signed 64-bit integers
'%I64u' for unsigned 64-bit integers

Great!