The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Farabi on July 27, 2010, 11:19:19 AM

Title: Formating Signed string
Post by: Farabi on July 27, 2010, 11:19:19 AM
Hi,
On my currency if you want to write 1 million is 1.000.000 but on English it was 1,000,000 is there any function to format the string to my currency format?
Title: Re: Formating Signed string
Post by: Geryon on July 27, 2010, 11:57:41 AM
http://msdn.microsoft.com/en-us/library/dd318083.aspx
Title: Re: Formating Signed string
Post by: frktons on July 27, 2010, 12:44:20 PM
We worked for a while on this matter on this thread:
http://www.masm32.com/board/index.php?topic=13939.0

Ciao
Title: Re: Formating Signed string
Post by: frktons on July 27, 2010, 12:48:54 PM
And if you speak C, this is the C version that does the same for
integer number only:

//-----------------------------------------------------------------------------------------------
// Function prototype for itoas(). Takes in the number to
// format, the pointer of the buffer to fill, and the thousand separator
// to use. Returns the lenght of the generated string.
//-----------------------------------------------------------------------------------------------

int itoas(long num, char [], char sep);


and:


//---------------------------------------------------------------
// itoas() - iMalc version updated ver. 0.8
//---------------------------------------------------------------
int itoas(long snum, char s[], char sep)
{
    char *ps = s;
    unsigned long num1 = snum, num2, num3, div;
    if (snum < 0) {
        *ps++ = '-';
        num1 = -snum;
    }
    if (num1 < 10000) {
        if (num1 < 10) goto L1;
        if (num1 < 100) goto L2;
        if (num1 < 1000) goto L3;
    } else {
        num2 = num1 / 10000;
        num1 -= num2 * 10000;
        if (num2 < 10000) {
            if (num2 < 10) goto L5;
            if (num2 < 100) goto L6;
            if (num2 < 1000) goto L7;
        } else {
            num3 = num2 / 10000;
            num2 -= num3 * 10000;
            if (num3 >= 10) {
                *ps++ = '0' + (char)(div = (num3*6554UL)>>16); num3 -= div*10;
                *ps++ = sep;
            }
            *ps++ = '0' + (char)(num3);
        }
        *ps++ = '0' + (char)(div = (num2*8389UL)>>23); num2 -= div*1000;
L7:
        *ps++ = '0' + (char)(div = (num2*5243UL)>>19); num2 -= div*100;
        *ps++ = sep;
L6:
        *ps++ = '0' + (char)(div = (num2*6554UL)>>16); num2 -= div*10;
L5:
        *ps++ = '0' + (char)(num2);
    }
    *ps++ = '0' + (char)(div = (num1*8389UL)>>23); num1 -= div*1000;
    *ps++ = sep;
L3:
    *ps++ = '0' + (char)(div = (num1*5243UL)>>19); num1 -= div*100;
L2:
    *ps++ = '0' + (char)(div = (num1*6554UL)>>16); num1 -= div*10;
L1:
    *ps++ = '0' + (char)(num1);
    *ps = '\0';
    return ps - s;
}


to adapt it to your needs, or to translate it into ASM is up to you.
I didn't translate it yet.

Enjoy
Title: Re: Formating Signed string
Post by: Farabi on July 27, 2010, 01:47:33 PM
Quote from: frktons on July 27, 2010, 12:48:54 PM
And if you speak C, this is the C version that does the same for
integer number only:

//-----------------------------------------------------------------------------------------------
// Function prototype for itoas(). Takes in the number to
// format, the pointer of the buffer to fill, and the thousand separator
// to use. Returns the lenght of the generated string.
//-----------------------------------------------------------------------------------------------

int itoas(long num, char [], char sep);


and:


//---------------------------------------------------------------
// itoas() - iMalc version updated ver. 0.8
//---------------------------------------------------------------
int itoas(long snum, char s[], char sep)
{
    char *ps = s;
    unsigned long num1 = snum, num2, num3, div;
    if (snum < 0) {
        *ps++ = '-';
        num1 = -snum;
    }
    if (num1 < 10000) {
        if (num1 < 10) goto L1;
        if (num1 < 100) goto L2;
        if (num1 < 1000) goto L3;
    } else {
        num2 = num1 / 10000;
        num1 -= num2 * 10000;
        if (num2 < 10000) {
            if (num2 < 10) goto L5;
            if (num2 < 100) goto L6;
            if (num2 < 1000) goto L7;
        } else {
            num3 = num2 / 10000;
            num2 -= num3 * 10000;
            if (num3 >= 10) {
                *ps++ = '0' + (char)(div = (num3*6554UL)>>16); num3 -= div*10;
                *ps++ = sep;
            }
            *ps++ = '0' + (char)(num3);
        }
        *ps++ = '0' + (char)(div = (num2*8389UL)>>23); num2 -= div*1000;
L7:
        *ps++ = '0' + (char)(div = (num2*5243UL)>>19); num2 -= div*100;
        *ps++ = sep;
L6:
        *ps++ = '0' + (char)(div = (num2*6554UL)>>16); num2 -= div*10;
L5:
        *ps++ = '0' + (char)(num2);
    }
    *ps++ = '0' + (char)(div = (num1*8389UL)>>23); num1 -= div*1000;
    *ps++ = sep;
L3:
    *ps++ = '0' + (char)(div = (num1*5243UL)>>19); num1 -= div*100;
L2:
    *ps++ = '0' + (char)(div = (num1*6554UL)>>16); num1 -= div*10;
L1:
    *ps++ = '0' + (char)(num1);
    *ps = '\0';
    return ps - s;
}


to adapt it to your needs, or to translate it into ASM is up to you.
I didn't translate it yet.

Enjoy

I prefer Ghandi method. Easier and simpler.
Title: Re: Formating Signed string
Post by: frktons on July 27, 2010, 04:31:05 PM
Quote from: Farabi on July 27, 2010, 01:47:33 PM
I prefer Ghandi method. Easier and simpler.

The bazaar is open till midnight, choose whatever you like  :P

By the way, the C version is the fastest, in case you need this info.  :U
Title: Re: Formating Signed string
Post by: hoverlees on July 28, 2010, 05:31:19 AM
But I want to know which one is the float point of your currency?  :eek
Title: Re: Formating Signed string
Post by: hutch-- on July 28, 2010, 05:36:38 AM
Onan,

Just get the length of the currency string, see how many 3 character blocks are in it them write the string to another larger buffer with the added characters for your currency format.

here is another way to do it as long as there is no fraction and decimal point. IE "1234567890" but not "1234567890.00".


IF 0  ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                      Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    include \masm32\include\masm32rt.inc

    fmtstr PROTO :DWORD,:DWORD

    .data
      curr db "1234567890",0
      buff db "                              ",0

      pcur dd curr
      pbuf dd buff

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    invoke fmtstr,pcur,pbuf

    print pbuf,13,10

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

fmtstr proc psrc:DWORD,pdst:DWORD

    push ebx

    invoke szRev,psrc,psrc      ; overwrite original

    mov ecx, psrc
    mov edx, pdst
    xor ebx, ebx

  lbl0:
    mov al, [ecx]
    test al, al
    jz lbl2
    add ecx, 1
   
    cmp ebx, 3
    jne lbl1

  ; ---------------------------------------
  ; add the seperator every third character
  ; ---------------------------------------
    mov BYTE PTR [edx], ","     ; put your preferred character here.
    add edx, 1
    xor ebx, ebx                ; reset counter to zero
  ; ---------------------------------------

  lbl1:
    add ebx, 1
    mov [edx], al
    add edx, 1
    jmp lbl0

  lbl2:
    mov BYTE PTR [edx], 0       ; terminate output buffer
    invoke szRev,pdst,pdst      ; reverse the output buffer

    pop ebx

    ret

fmtstr endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Title: Re: Formating Signed string
Post by: Farabi on July 28, 2010, 06:05:39 AM
Quote from: hutch-- on July 28, 2010, 05:36:38 AM
Onan,

Just get the length of the currency string, see how many 3 character blocks are in it them write the string to another larger buffer with the added characters for your currency format.

Yeah I did. Thanks anyway.
Title: Re: Formating Signed string
Post by: raymond on July 29, 2010, 01:24:50 AM
Quote from: hoverlees on July 28, 2010, 05:31:19 AM
But I want to know which one is the float point of your currency? :eek

Many countries use the coma as the decimal delimiter (instead of the "decimal point").
Title: Re: Formating Signed string
Post by: hoverlees on July 29, 2010, 08:52:24 AM
Quote from: raymond on July 29, 2010, 01:24:50 AM
Quote from: hoverlees on July 28, 2010, 05:31:19 AM
But I want to know which one is the float point of your currency? :eek

Many countries use the coma as the decimal delimiter (instead of the "decimal point").

thanks :bdg
Title: Re: Formating Signed string
Post by: Geryon on July 29, 2010, 09:22:43 AM
As you notice my english is not so good
No offence, but Isn't it that you are trying to achieve ?
Title: Re: Formating Signed string
Post by: frktons on July 29, 2010, 11:57:27 AM
Quote from: Geryon on July 29, 2010, 09:22:43 AM
As you notice my english is not so good
No offence, but Isn't it that you are trying to achieve ?

Yes sir. That's exactly what farabi was looking for. Maybe he doesn't like
calling APIs functions, so he preferred to use an hand-made solution.  :P

Any reason you used test.bat instead of test.asm?

And a last thing, in order to compile with qeditor and MASM32 package,
I had to modidy some small things:


;---------------------------------------------------------------------------------
; Format currency values with thousand separator, decimal point and
; currency symbol based on LOCALE_USER_DEFAULT.
;---------------------------------------------------------------------------------

.nolist
include \masm32\include\masm32rt.inc

.686

.data
    szMoney     DB  "12345678910", 0
    szTitle     DB  "Currency Test", 0
   
.data?
    szBuffer    DB  255 dup(?)

.code
start:
    invoke GetCurrencyFormat, LOCALE_USER_DEFAULT  \
                            , 0                    \
                            , offset szMoney       \
                            , NULL                 \
                            , offset szBuffer      \
                            , 255
                           
    invoke MessageBox, NULL                     \
                     , offset szBuffer          \
                     , offset szTitle           \
                     , MB_OK or MB_SYSTEMMODAL 
                     
    invoke ExitProcess, -1
end start


It was ready for EasyCode, probably not for qeditor  ::)

Title: Re: Formating Signed string
Post by: jj2007 on July 29, 2010, 12:41:03 PM
Just a small hint: With invoke, you don't need backslashes, a comma is enough

    invoke GetCurrencyFormat, LOCALE_USER_DEFAULT,
    0,
    offset szMoney,
    NULL,
    offset szBuffer,
    SIZEOF szBuffer


Or, on one line: invoke GetCurrencyFormat, LOCALE_USER_DEFAULT, 0, offset szMoney, NULL, offset szBuffer, SIZEOF szBuffer
Title: Re: Formating Signed string
Post by: Geryon on July 29, 2010, 02:12:02 PM
Quote from: frktons on July 29, 2010, 11:57:27 AM
Any reason you used test.bat instead of test.asm?
Yes, when I double click that .bat file, it will begin to execute masm compile commands.
So, without a IDE, it provide easy build.

Quote from: jj2007 on July 29, 2010, 12:41:03 PM
Just a small hint: With invoke, you don't need backslashes, a comma is enough
Thank you, I will do that.
Acutally, I've been always confused about that.
Let's take realy long line

invoke Function, arg1, arg2, arg3, arrrrrrrrrg4, arg5, ..... etc

How should I divide it ?
like that (C style)

invoke function arg1,
arg2,
arg3,
etc...


or like this

invoke function arg1, arg2, arg3
arg4, arg5, arg6
Title: Re: Formating Signed string
Post by: Farabi on July 30, 2010, 12:40:59 AM
Man I though there is no API for this, anyway I modify Ghandi function to suit my need


FormatString PROC pInput:DWORD,pOutput:DWORD
; Created by Ghandi at MASM Forum
;Get length of string
LOCAL rmnd:dword
LOCAL len:dword
mov edi,pInput
xor eax,eax
or ecx,-1
repne scasb
add ecx,1
not ecx

;Get number of iterations plus remainder
mov eax,ecx
mov ecx,3
xor edx,edx
div ecx
mov rmnd,edx
mov len,eax

;Set source and destination registers, string length and then move across remainder as left most of string
mov esi,pInput
mov edi,pOutput
mov ecx,edx
rep movsb

;Set counter to number of iterations
mov ecx,eax

;Set EDX to AND mask
mov edx,0FFFFFFh

;We'll start each part here with the ',' and then take a full DWORD from EDI as we know there is the NULL byte at the end.
mov ebx,','

@@ThreeCharLoop:
;Save delimiter
.if rmnd!=0
mov byte ptr [edi],bl
add edi,1
.else
.if ecx!=len
mov byte ptr [edi],bl
add edi,1
.endif
.endif
;Load source DWORD
lodsd

;Strip upper byte of EAX with AND mask in EDX
and eax,edx

;Save DWORD to destination as null terminated 3 char string
stosd

;There is a byte overlap from the LODSD/STOSD, decrement source and destination by one byte
sub esi,1
sub edi,1

;Loop like this until ECX == 0
sub ecx,1
jnz @@ThreeCharLoop

;Get length of output string
mov edi,pOutput
xor eax,eax
or ecx,-1
repne scasb
add ecx,1
not ecx

;Set return value
mov eax,ecx
Ret

FormatString EndP


That is your ghandi.
Title: Re: Formating Signed string
Post by: Farabi on July 30, 2010, 01:55:40 AM
Anyone know how to set the CURRENCYFMT structure?

I tried this but not working

mov cfmt.NumDigits,LOCALE_ICURRDIGITS
mov cfmt.LeadingZero,LOCALE_ILZERO
mov cfmt.Grouping,3
mov cfmt.lpDecimalSep,CTXT(",")
mov cfmt.lpThousandSep,CTXT(".")
mov cfmt.NegativeOrder,LOCALE_INEGCURR
mov cfmt.PositiveOrder,LOCALE_ICURRENCY
mov cfmt.lpCurrencySymbol,CTXT("Rp. " )
Title: Re: Formating Signed string
Post by: frktons on July 30, 2010, 07:25:21 AM
Quote from: jj2007 on July 29, 2010, 12:41:03 PM
Just a small hint: With invoke, you don't need backslashes, a comma is enough

    invoke GetCurrencyFormat, LOCALE_USER_DEFAULT,
    0,
    offset szMoney,
    NULL,
    offset szBuffer,
    SIZEOF szBuffer


Or, on one line: invoke GetCurrencyFormat, LOCALE_USER_DEFAULT, 0, offset szMoney, NULL, offset szBuffer, SIZEOF szBuffer


Thanks Jochen  :U

Quote from: Farabi on July 30, 2010, 01:55:40 AM
Anyone know how to set the CURRENCYFMT structure?

I tried this but not working

mov cfmt.NumDigits,LOCALE_ICURRDIGITS
mov cfmt.LeadingZero,LOCALE_ILZERO
mov cfmt.Grouping,3
mov cfmt.lpDecimalSep,CTXT(",")
mov cfmt.lpThousandSep,CTXT(".")
mov cfmt.NegativeOrder,LOCALE_INEGCURR
mov cfmt.PositiveOrder,LOCALE_ICURRENCY
mov cfmt.lpCurrencySymbol,CTXT("Rp. " )


Did you include the necessary headers?
Post the entire pgm, it'll be easier to see is something is missing.
Title: Re: Formating Signed string
Post by: hutch-- on July 31, 2010, 06:52:23 AM
 :bg

Looking at the code posted to do the job, now you know why I roll my own.  :P
Title: Re: Formating Signed string
Post by: frktons on August 03, 2010, 08:46:13 AM
The long searched API to format integer numbers with comma/point separator is:

The GetNumberFormat function formats a number string as a number string customized for a specified locale.

int GetNumberFormat(

    LCID Locale, // locale for which number string is to be formatted
    DWORD dwFlags, // bit flag that controls the function's operation
    LPCTSTR lpValue, // pointer to input number string
    CONST NUMBERFMT *lpFormat, // pointer to a formatting information structure
    LPTSTR lpNumberStr, // pointer to output buffer
    int cchNumber // size of output buffer
   );


Parameters

Locale

Specifies the locale for which the number string is to be formatted. If lpFormat is NULL, the function formats the string according to the number format for this locale. If lpFormat is not NULL, the function uses the locale only for formatting information not specified in the NUMBERFMT structure (for example, the locale's string value for the negative sign).
This parameter can be a locale identifier created by the MAKELCID macro, or one of the following predefined values:

LOCALE_SYSTEM_DEFAULT Default system locale.
LOCALE_USER_DEFAULT Default user locale.


dwFlags

Contains a bit flag that controls the operation of the function. If lpFormat is non-NULL, this parameter must be zero.
If lpFormat is NULL, you can specify the LOCALE_NOUSEROVERRIDE flag to format the string using the system default number format for the specified locale; or you can specify zero to format the string using any user overrides to the locale's default number format

lpValue

Points to a null-terminated string containing the number string to format.
This string can only contain the following characters:

· Characters '0' through '9'
· One decimal point (dot) if the number is a floating-point value
· A minus sign in the first character position if the number is a negative value

All other characters are invalid. The function returns an error if the string pointed to by lpValue deviates from these rules.

lpFormat

Pointer to a NUMBERFMT structure that contains number formatting information. All members in the structure pointed to by lpFormat must contain appropriate values.
If lpFormat is NULL, the function uses the number format of the specified locale.



lpNumberStr

Points to a buffer to receive the formatted number string.

cchNumber

Specifies the size, in bytes (ANSI version) or characters (Unicode version), of the lpNumberStr buffer. If cchNumber is zero, the function returns the number of bytes or characters required to hold the formatted number string, and the buffer pointed to by lpNumberStr is not used.



Return Values

If the function succeeds, the return value is the number of bytes (ANSI version) or characters (Unicode version) written to the buffer pointed to by lpNumberStr, or if the cchNumber parameter is zero, the number of bytes or characters required to hold the formatted number string.
If the function fails, the return value is zero. To get extended error information, call GetLastError. GetLastError may return one of the following error codes:

ERROR_INSUFFICIENT_BUFFER
ERROR_INVALID FLAGS
ERROR_INVALID_PARAMETER



If you don't need the currency sign, or the fractional part used for cents
in currency format, the API of choice should be GetNumberFormat
:U
Title: Re: Formating Signed string
Post by: frktons on August 03, 2010, 09:32:54 AM
And the prog to use GetNumberFormat() API:

;---------------------------------------------------------------------------------
; Format integer values with thousand separator.
; Separator symbol based on LOCALE_USER_DEFAULT.
;---------------------------------------------------------------------------------

.nolist
include \masm32\include\masm32rt.inc

.686

.data
    Number      DB  "12345678910", 0
    BoxTitle      DB  "Num format Test", 0
   
.data?
    Buffer      DB  255 dup(?)

.code
start:
    invoke GetNumberFormat, LOCALE_USER_DEFAULT,
                            0,
                            offset Number,
                            NULL,
                            offset Buffer,
                            255
                           
    invoke MessageBox, NULL,
                       offset Buffer,
                       offset BoxTitle,
                       MB_OK ;  or MB_SYSTEMMODAL
                     
    invoke ExitProcess, -1
end start


There is still a little flaw in the prog. It displays the decimal point and
two zeros at the end of the string, and it is wrong. On my pc it should be
a decimal comma, the point is used for thousand separator.

A last thing. If I want to get rid of the decimal part altogether, what have
I to change in the prog?  ::)

Edit: I tried to use LOCALE_SYSTEM_DEFAULT instead of LOCALE_USER_DEFAULT
but it is not defined, I guess in the windows include  ::)

In windows.inc I found:

LOCALE_USER_DEFAULT                  equ 0400h

Could it depends on it the decimal point in my Italian PC?
Title: Re: Formating Signed string
Post by: frktons on August 03, 2010, 11:04:49 AM
Well, probably I have to play a little with these structure fields:

NUMBERFMTA STRUCT
  NumDigits         DWORD      ?
  LeadingZero       DWORD      ?
  Grouping          DWORD      ?
  lpDecimalSep      DWORD      ?
  lpThousandSep     DWORD      ?
  NegativeOrder     DWORD      ?
NUMBERFMTA ENDS

NUMBERFMT  equ  <NUMBERFMTA>

to get the job done.  :P
According to Win API doc:

The NUMBERFMT structure contains information that defines the format of a number string. The GetNumberFormat function uses this information to customize a number string for a specified locale.

typedef struct _numberfmt { 
    UINT      NumDigits;
    UINT      LeadingZero;
    UINT      Grouping;
    LPTSTR    lpDecimalSep;
    LPTSTR    lpThousandSep;
    UINT      NegativeOrder;
} NUMBERFMT;


Members

NumDigits

Specifies the number of fractional digits. This is equivalent to the locale information specified by the LCTYPE constant value LOCALE_IDIGITS.

LeadingZero

Specifies whether to use leading zeroes in decimal fields. This is equivalent to the locale information specified by the LCTYPE constant value LOCALE_ILZERO.

Grouping

Specifies the size of each group of digits to the left of the decimal. Values in the range 0 - 9 are valid.

lpDecimalSep

Points to a null-terminated decimal separator string.

lpThousandSep

Points to a null-terminated thousand separator string.

NegativeOrder

Specifies the negative number mode. This is equivalent to the locale information specified by the LCTYPE constant value LOCALE_INEGNUMBER.

Remarks

For more information about the LCTYPE constants, see LCTYPE Constants.

Title: Re: Formating Signed string
Post by: frktons on August 03, 2010, 11:49:16 AM
After a bit experimentation I came out with this working solution:

;---------------------------------------------------------------------------------
; Format integer values with thousand separator.
; Separator symbol and decimal symbol based on NUMBERFMT structure.
;---------------------------------------------------------------------------------
; format_number2.asm
;---------------------------------------------------------------------------------

.nolist
include \masm32\include\masm32rt.inc

.686

.data
    Number      DB  "12345678910", 0
    BoxTitle    DB  "Num format Test", 0
    Sep         DB  ",",0
    lpSep       DD  Sep
    Tsep        DD  ".",0
    lpTsep      DD  Tsep 
 
   
.data?
    Buffer      DB  255 dup(?)
    NumFmt      NUMBERFMT <>
;---------------------------------------------------------------------------------
; Structure for number formatting
;---------------------------------------------------------------------------------   
; NUMBERFMTA STRUCT
;    NumDigits         DWORD      ?
;    LeadingZero       DWORD      ?
;    Grouping          DWORD      ?
;    lpDecimalSep      DWORD      ?
;    lpThousandSep     DWORD      ?
;    NegativeOrder     DWORD      ?
; NUMBERFMTA ENDS
;
; NUMBERFMT  equ  <NUMBERFMTA>     
;---------------------------------------------------------------------------------
.code
start:

    mov NumFmt.NumDigits, 0               ; No decimal digits
    mov NumFmt.LeadingZero, 0             ; No leading zeroes
    mov NumFmt.Grouping, 3                ; Groups of three numbers
    mov NumFmt.lpDecimalSep,  offset Sep  ; Pointer to NULL terminated string with the decimal separator
    mov NumFmt.lpThousandSep, offset Tsep ; Pointer to NULL terminated string with the thousand separator
    mov NumFmt.NegativeOrder, 0           ; Negative number mode

    invoke GetNumberFormat, NULL,
                            0,
                            offset Number,
                            offset NumFmt,
                            offset Buffer,
                            255
                           
    invoke MessageBox, NULL,
                       offset Buffer,
                       offset BoxTitle,
                       MB_OK ;  or MB_SYSTEMMODAL
                     
    invoke ExitProcess, -1
end start


Now it displays only the integer value, without trailing decimal zeroes, if not needed,
and with the correct decimal comma  separator if a decimal value is passed.