Author Topic: is it a c++ number ?  (Read 5814 times)

ToutEnMasm

  • Member
  • *****
  • Posts: 1189
    • EditMasm
is it a c++ number ?
« on: September 13, 2014, 10:40:57 PM »

I search a function who can answer it is a number for this c++ string numbers:
Quote
   ;rien = 0x0;
   ;rien = 0X245f;
   ;rien = 0X245flu;
   ;chose = 245u;
   ;grand = 0x1df56bULL;
   ;grand = 0x1df56bi64;
   ;0.2E-01
   ;reel = 0.1;
   ;0x7ffffffffi8 I16 I32 i64
   ;0756 octal
   ;rien = -1.18E - 38
I have tried the atoi,strtol.. with no result.
One idea ?.



Fa is a musical note to play with CL

jj2007

  • Member
  • *****
  • Posts: 7548
  • Assembler is fun ;-)
    • MasmBasic
Re: is it a c++ number ?
« Reply #1 on: September 13, 2014, 11:21:32 PM »
Looks like really malformed stuff. You may have to reformat them a little bit, like eliminating spaces, or adding suffixes that work better than grand ... bULL 8)

Even MasmBasic's MovVal can't interpret some of them:

include \masm32\MasmBasic\MasmBasic.inc      ; download
Guess MACRO arg
  MovVal MyR8, arg
  PrintLine Str$(MyR8), Tb$, arg
ENDM
.data?
MyR8      REAL8 ?

  Init
  Guess "0x0"
  Guess "0X245f"
  Guess "0X245flu"
  Guess "245u"
  Guess "0x1df56bULL"
  Guess "0x1df56bi64"
  Guess "0.2E-01"
  Guess "0.1"
  Guess "0x7ffffffffi8"
  Guess "0756"
  Guess "-1.18E - 38"
  Exit
end start

0.0     0x0
9311.000        0X245f
2383982.0       0X245flu
2383982.0       245u
8.041976e+09    0x1df56bULL
8.041972e+09    0x1df56bi64
0.02000000      0.2E-01
0.1000000       0.1
8.727374e+12    0x7ffffffffi8
756.0000        0756
-1.180000e-16   -1.18E - 38

What are these numbers, part of a database? Any documentation for the flu, bULL, fi8 suffixes? It must be fi8 if the number is 8 chars long: 0x7ffffffffi8

ToutEnMasm

  • Member
  • *****
  • Posts: 1189
    • EditMasm
Re: is it a c++ number ?
« Reply #2 on: September 13, 2014, 11:35:07 PM »
Quote
Looks like really malformed stuff.
All those chains are allowed in c++,you can compile them.
All i want is a function who answer:
Quote
0 ; chain
1 ;number
; in option can answer
2 ;it is a real
3 ;it is unsigned ....and so on
Fa is a musical note to play with CL

jj2007

  • Member
  • *****
  • Posts: 7548
  • Assembler is fun ;-)
    • MasmBasic
Re: is it a c++ number ?
« Reply #3 on: September 14, 2014, 12:10:12 AM »
All those chains are allowed in c++,you can compile them.

C++ compiles a "chain" that looks like hex but has 9 chars?
0x7ffffffffi8

ToutEnMasm

  • Member
  • *****
  • Posts: 1189
    • EditMasm
Re: is it a c++ number ?
« Reply #4 on: September 14, 2014, 01:00:37 AM »
compiled without problem

here is my test prog  ,Visual C express edition 2010,cl /c /FA /Gm- /GS- /Zi

Code: [Select]
// crt_strtod.c
// This program uses strtod to convert a
// string to a double-precision value; strtol to
// convert a string to long integer values; and strtoul
// to convert a string to unsigned long-integer values.
//

#include <stdlib.h>
#include <stdio.h>

int main( void )
{
char   *string, *stopstring;
double x;
long   l;
int    base;
unsigned long ul;


//string = "-1.18E - 38";//"255";//"0X245flu";
string = "0x7ffffffffi8";
base=atoi(string);
base = 0x7ffffffffi8;
printf("   atoi = %x\n", base );

x = strtod( string, &stopstring );
printf( "string = %s\n", string );
printf("   strtod = %f\n", x );
printf("   Stopped scan at: %s\n\n", stopstring );

string = "-10110134932This stopped it";
l = strtol( string, &stopstring, 10 );
printf( "string = %s\n", string );
printf("   strtol = %ld\n", l );
printf("   Stopped scan at: %s\n\n", stopstring );

string = "0X245flu"; //"10110134932";
printf( "string = %s\n", string );

// Convert string using base 2, 4, and 8:
for( base = 2; base <= 8; base *= 2 )
{
// Convert the string:
ul = strtoul( string, &stopstring, base );
printf( "   strtol = %ld (base %d)\n", ul, base );
printf( "   Stopped scan at: %s\n", stopstring );
}
Fa is a musical note to play with CL

jj2007

  • Member
  • *****
  • Posts: 7548
  • Assembler is fun ;-)
    • MasmBasic
Re: is it a c++ number ?
« Reply #5 on: September 14, 2014, 01:51:04 AM »
      base = 0x7ffffffffi8;   
      printf("   atoi = %x\n", base );

Using VC 2010 Express, my output is atoi = ffffffff
Does that make sense to you?

ToutEnMasm

  • Member
  • *****
  • Posts: 1189
    • EditMasm
Re: is it a c++ number ?
« Reply #6 on: September 14, 2014, 04:08:10 AM »

seems that those functions don't accept hexadecimal chain. "stopped ar 0x , stopped at fffff"
That's all I can said.
Fa is a musical note to play with CL

jj2007

  • Member
  • *****
  • Posts: 7548
  • Assembler is fun ;-)
    • MasmBasic
Re: is it a c++ number ?
« Reply #7 on: September 14, 2014, 04:59:33 AM »
It's much worse, actually:
      base = 0x7ffffffffi8;   // this COMPILES without warnings ...
      printf("   atoi = %x\n", base ); // ... and outputs ffffffff, not 7fff...

So it's (your choice)
a) a fat bug in MSVC
b) a feature
c) garbage in, garbage out

qWord

  • Member
  • *****
  • Posts: 1454
  • The base type of a type is the type itself
    • SmplMath macros
Re: is it a c++ number ?
« Reply #8 on: September 14, 2014, 05:12:37 AM »
Just checking if a string holds a numeric literal shouldn't be that complicated. Below a spaghetti-code-style procedure that also support these MSVS specific (nonstandard) type suffixes (i64,ui64,...).
Code: [Select]
include \masm32\include\masm32rt.inc
.code

MSVC EQU -1

stackframe off
; accepts C++ integer and FP literals and C99 hexadecimal FP literals.
; Leading and trailing whitespaces (ascii <= 20h) are ignored. No size checking is done.
; Return: nonzero value if range [begin,end) is a numberic literal.
is_numeric_literal proc uses esi edi ebx pbegin: ptr TCHAR,pend: ptr TCHAR

push esi
push edi
push ebx
push ebp
mov ebp,esp

mov esi,PTCHAR ptr [esp+4*4+4]
mov edi,PTCHAR ptr [esp+4*4+8]
xor ecx,ecx
cmp esi,edi
jae @end

; esi = ptr next character
; edi = ptr one past end
; ebx = used for digit test
; eax = current digit/character
; ecx = number of valid digits

; skip leading blanks and possible sign
call @spaces
.if eax == '+' || eax == '-'
call @spaces
.endif

;/**
; * check first digit
; */

mov ebx,'9'-'0' ; @digit tests for decimal digits

cmp esi,edi ; if there is only one char., it can only be a decimal digit
jae @F

; special treatment for 0 as first digit
cmp eax,'0'
je @start_with_zero

@@: cmp eax,'.' ; --> FP literal
je @F

; test: decimal digit
sub eax,'0'
.if eax <= ebx
or ecx,1
.endif

@decimal:
;/**
; *  read up further decimal digits
; */
call @digits

;/* test and process decimal floating point literals */
.if eax == '.'
@@: call @digits
cmp eax,'e'
je @exponent
cmp eax,'E'
je @exponent
jmp @fp_suffix
.endif
cmp eax,'e'
je @exponent
cmp eax,'E'
je @exponent

;/**
; * The scanned number is an integer literal.
; *  --> test for possible type-suffix
; */
@integer_suffix:
mov ebx,@next
mov edx,eax
or edx,100000y
.if edx == 'u'
call ebx
.if edx == 'l'
call ebx
.if edx == 'l'
call ebx
.endif
IFDEF MSVC
.elseif edx == 'i'
jmp @F
ENDIF
.endif
.elseif edx == 'l'
call ebx
.if edx == 'l'
call ebx
.if edx == 'u'
call ebx
.endif
.elseif edx == 'u'
call ebx
.endif
IFDEF MSVC
.elseif edx == 'i' || eax == 'I'
@@: call ebx
.if eax == '6'
call ebx
cmp eax,'4'
jne @fail
.elseif eax == '3'
call ebx
cmp eax,'2'
jne @fail
.elseif eax == '1'
call ebx
cmp eax,'6'
jne @fail
.elseif eax == '8'
call ebx
.else
jmp @fail
.endif
call ebx
ENDIF
.endif
cmp eax,20h
ja @fail
jna @check_end

@end:
;/* the number of succesfully scanned digits (in ECX) determines the result */
mov eax,ecx
mov esp,ebp
pop ebp
pop ebx
pop edi
pop esi
retn 8

@next: ; get the next character
cmp esi,edi
jae @end
movzx eax,TCHAR ptr [esi]
add esi,TCHAR
mov edx,eax
or edx,100000y ; to lower case
retn 0

@start_with_zero:
;/**
; * Get next next char. and test for prefix:
; *   "0x" -> hexadecimal literal
; *   "0b" -> binary literal
; */
movzx eax,TCHAR ptr [esi]
add esi,TCHAR
mov edx,eax
or edx,100000y
sub eax,'0'

.if edx == 'x'
call @hex_digits
.if eax == '.'
call @hex_digits
cmp eax,'p'
je @exponent
cmp eax,'P'
je @exponent
jne @fp_suffix
.endif
cmp eax,'p'
je @exponent
cmp eax,'P'
je @exponent
jne @integer_suffix
.endif


.if edx == 'b'
mov ebx,'1'-'0'
push @integer_suffix
jmp @digits
.else
;/**
; * Possible cases:
; *   - octal integer literal
; *   - decimal FP literal with leading zero(s)
; */

or ecx,1 ; count leading zero

;/* scann for '.', 'e' or 'E' (indicates a decimal FP lit.) */
mov edx,esi
.while edx < edi
movzx eax,TCHAR ptr [edx]
cmp eax,'.'
je @decimal
or eax,100000y
cmp eax,'e'
je @decimal
add edx,TCHAR
.endw
;/* it must be an octal integer literal (or invalid) */
mov ebx,'7'-'0'
push @integer_suffix
jmp @digits
.endif


@spaces: ; skip whitespace characters (ascii <= 32)
@@: cmp esi,edi
jae @end ; end of range reached
movzx eax,TCHAR ptr [esi]
add esi,TCHAR
cmp eax,20h
jna @B

retn 0


@@:
add ecx,1
@digits: ; scan didigts (decimal, binary or octal)
cmp esi,edi
jae @end ; end of range reached
movzx eax,TCHAR ptr [esi]
add esi,TCHAR
sub eax,'0'
cmp eax,ebx
jna @B

add eax,'0'
retn 0

@@:
add ecx,1
@hex_digits: ; scan hexadecimal digits
cmp esi,edi
jae @end ; end of range reached
movzx eax,TCHAR ptr [esi]
mov edx,eax
add esi,TCHAR
or edx,100000y
sub eax,'0'
sub edx,'a'
cmp eax,'9'-'0'
jna @B
cmp edx,'f'-'a'
jna @B

add eax,'0'
retn 0


@exponent: ; scan exponent
test ecx,ecx
je @end ; the number must already have digits!

xor ecx,ecx ; zero ECX -> there must be exponent digits for success.
cmp esi,edi
jae @end ; end of range reached

; skip sign
movzx eax,TCHAR ptr [esi]
.if eax == '+' || eax == '-'
add esi,TCHAR
.endif

; get decimal exponent digits
mov ebx,'9'-'0'
call @digits

; check for FP suffix 'f', 'F', 'l' and 'L'
@fp_suffix:
or eax,100000y
cmp eax,'f'
je @check_end
cmp eax,'l'
je @check_end
cmp eax,20h
ja @fail

@check_end: ; only whitespaces are allowed after the literal
@@: cmp esi,edi
jae @end
movzx eax,TCHAR ptr [esi]
add esi,TCHAR
cmp eax,20h
jna @B

@fail:
xor eax,eax
mov esp,ebp
pop ebp
pop ebx
pop edi
pop esi
retn 8


is_numeric_literal endp
stackframe on

lit_test proc uses esi psz: ptr TCHAR

mov esi,psz
add esi,len(esi)

.if rv(is_numeric_literal,psz,esi)
print "  valid: "
.else
print "invalid: "
.endif
print psz,13,10

ret

lit_test endp

main proc

fn lit_test,"123"
fn lit_test,"123.456"
fn lit_test," 123"
fn lit_test," 123  "
fn lit_test," 123a"
fn lit_test," .123f"
fn lit_test," .123L "
fn lit_test,"123.456E+78"
fn lit_test,"-123"
fn lit_test,"   -123.  "
fn lit_test,"0x123"
fn lit_test,"  0x123  "
fn lit_test," 0x123."
fn lit_test," 0x123. "
fn lit_test," 0x12f.4f"
fn lit_test," 0xf123.fp+123"
fn lit_test," 0xf123.fp123"
fn lit_test," 0xf123.fp+123 "
fn lit_test," 0xf123.fp+123l "
fn lit_test," 0xf123.fp+123F"
fn lit_test," 01234567 "
fn lit_test," 012345677 "
fn lit_test," 0123456789"
fn lit_test," 0b1234567 "
fn lit_test," 0b1 "
fn lit_test," 0b"
fn lit_test," 0x"
fn lit_test," 0x0"
fn lit_test," 0 "
fn lit_test,"0"
fn lit_test,"00"
fn lit_test,"1"
fn lit_test," 1"
fn lit_test," 1 "
fn lit_test,"0b101010111"
fn lit_test,"123."
fn lit_test,"0x.F"
fn lit_test,"0x.0p0"
fn lit_test,"1."
fn lit_test,"0.0"
fn lit_test,"0."
fn lit_test,".0"
fn lit_test,".0E-123"
fn lit_test,"1.0E0"
fn lit_test,"1.00E+0"
fn lit_test," +.0E0 "
fn lit_test," -0XFFFFFFFF "
fn lit_test," -0xffffffff "
fn lit_test,"0123"
fn lit_test,"0x.123p456-"
fn lit_test," 5555q"
fn lit_test," 123456ull "
fn lit_test," 0xff123ul "
fn lit_test," -0xff123lu "
fn lit_test,"0xff123llu "
fn lit_test,"123u"
fn lit_test,"456li"
fn lit_test,"0777777-"
fn lit_test," 0777E+3"
fn lit_test,"0123.456"
fn lit_test," 0x123fff.ffae"
fn lit_test,"0x123fff.ffae+23"
fn lit_test,"+9"
fn lit_test,"+666ull"
fn lit_test,"+666.000l"
fn lit_test,"  -  666.999e-666 "
fn lit_test," 123i64"
fn lit_test,"-123i32"
fn lit_test,"0x123fff.23u"
fn lit_test,"0x123fff.23i32"
fn lit_test,"0x123fffi32"
fn lit_test,"0x123fffi16"
fn lit_test,"0x123fffi8"
fn lit_test,"0x123fffi9"
fn lit_test,"0x123fffi64q"
fn lit_test,"0x123fffi8 asd"
fn lit_test,"00000.000002E-01"
fn lit_test," .000000E-01 "
fn lit_test,"0.01E-01"
fn lit_test,".9u"
fn lit_test,".E-1"

fn lit_test,"0x0"
fn lit_test,"0X245f"
fn lit_test,"0X245flu"
fn lit_test,"245u"
fn lit_test,"0x1df56bULL"
fn lit_test,"0x1df56bi64"
fn lit_test,"0.2E-01"
fn lit_test,"0.1"
fn lit_test,"0x7ffffffffi8"
fn lit_test,"0x7ffffffffI16"
fn lit_test,"0x7ffffffffI32"
fn lit_test,"0x7ffffffffI64"
fn lit_test,"0x7ffffffffuI32"
fn lit_test,"0756"
fn lit_test,"-1.18E - 38"
fn lit_test,"-1.18E-38"

inkey
exit
main endp
end main
MREAL macros - when you need floating point arithmetic while assembling!

ToutEnMasm

  • Member
  • *****
  • Posts: 1189
    • EditMasm
Re: is it a c++ number ?
« Reply #9 on: September 14, 2014, 04:26:37 PM »

Thanks to qword.

Just a question,I don't see what is the masm equivalent to "0xf123.fp+123l" ?.
Fa is a musical note to play with CL

ToutEnMasm

  • Member
  • *****
  • Posts: 1189
    • EditMasm
Re: is it a c++ number ?
« Reply #10 on: September 14, 2014, 06:29:12 PM »
Here is my own,using the same chains as qword
Code: [Select]
include \masm32\include\masm32rt.inc
.const
ZEROLOCALES MACRO dernierelocale:REQ
mov edx,edi
mov ecx,ebp
lea edi,dernierelocale
sub ecx,edi
xor eax,eax
shr ecx,2
rep stosd
mov edi,edx
ENDM
hexadecimal equ 1
decimal equ 2
octal equ 3
.data
chiffrehexa db "0","1","2","3","4","5","6","7","8","9","A","a","B","b","C","c","D","d","E","e","F","f",0
chiffredeci db "0","1","2","3","4","5","6","7","8","9",0
chiffreoctal db "0","1","2","3","4","5","6","7",0
.code


; accepts C++ integer and FP literals and C99 hexadecimal FP literals.
;accept only trimmed chain,no space tab at start and end
;accept octal,decimal,hexa,real numbers
; Leading and trailing whitespaces (ascii <= 20h) are ignored. No size checking is done.
; Return: zero chain,1 number

;*********************************************************************
;################################################################
;reçois l'adresse d'une donnée et détermine si c'est un chiffre,oui retourne 1
CertificationChiffre PROC uses esi edi ebx adrChiffre:DWORD
Local phrase[MAX_PATH]:BYTE
Local Efound:DWORD,Lfound,Pointfound,Ifound,Ufound,Pfound,Plusfound,Moinsfound
LOCAL  hexa:DWORD,reel,base
Local  retour:DWORD,CPT:DWORD
ZEROLOCALES CPT

;--------------------------------
;----------- vérifier la composition --------------
;le type binaire 011b n'est pas pris en compte
;0 char
mov esi,adrChiffre ;
xor eax,eax
.if byte ptr [esi] == 0
mov retour,0
jmp FindeCertificationChiffre
.endif
;----- real case ------------------
invoke lstrcpy,addr phrase,adrChiffre  ;don't modify the
lea esi,phrase
;-------------- All in lowercase,no space and no tab inside the chain ------------
mov ecx,"a" - "A"
mov edx,esi
Trier:
.if byte ptr [edx] != 0
mov al,byte ptr [edx]
.if al >= "a" && al <= "z"
sub al,cl
mov [edx],al
.endif
.if byte ptr [edx] == " " || byte ptr [edx] == 9
;edx not changed
;esi and edi move text without the start " " or tab
push esi
mov edi,edx
mov esi,edx
@@:
.if byte ptr [esi] == " " || byte ptr [edx] == 9
inc esi
jmp @B
.endif
.if byte ptr [esi] == 0
mov byte ptr [edi],0
pop esi
jmp endfiltre
.else
@@:
movsb
.if byte ptr [esi] != 0
jmp @B
.endif
mov byte ptr [edi],0
.endif
pop esi
.endif
inc edx
jmp Trier
.endif
endfiltre:

;one char
.if byte ptr [esi+1] == 0 ;un seul chiffre
;ne peut être que décimal
mov al,byte ptr [esi]
mov base,decimal
call composition
mov retour,edx ;0 chain,1 number
jmp FindeCertificationChiffre
.endif

;count the number of .
lea edx,phrase
mov ecx,0
@@:
.if byte ptr [edx] != 0 && byte ptr [edx] != "."
inc edx
jmp @B
.else
.if byte ptr [edx] == "."
inc ecx
inc edx
jmp @B
.endif
.endif
.if ecx > 1
jmp FindeCertificationChiffre
.endif
.if ecx == 1
mov base,hexadecimal
.endif

;--------- skip prefixes ----------------
lea esi,phrase
.if byte ptr [esi] == "+" || byte ptr [esi] == "-"
@@:
inc esi
.if byte ptr [esi] == " " || byte ptr [esi] == 9
jmp  @B
.endif
.endif
.if byte ptr [esi] == "0" ;octal
inc esi
.if base == 0
mov base,octal ;octal
.endif
.if byte ptr [esi] == "x" || byte ptr [esi] == "X"
inc esi
.if byte ptr [esi] == 0
mov retour,1
jmp FindeCertificationChiffre
.endif
mov base,hexadecimal
.endif
.endif
.if base == 0
mov base,decimal
.endif

; first char can be only a digit or a . or a x after prefix
mov al,byte ptr [esi]
.if al != 0
call composition
.if edx != 1 ;échec
.if byte ptr [esi] != "."
jmp FindeCertificationChiffre
.endif
.endif
.else
jmp FindeCertificationChiffre
.endif

;esi is on the first digit,continue until no digit
loopnumber:
inc esi
mov al,byte ptr [esi]
.if al != 0
call composition
.if edx != 1 ;Not a digit
;what is ?
.if byte ptr [esi] == "E"
inc Efound
.if Efound > 1
;not a number
jmp FindeCertificationChiffre
.endif
.elseif byte ptr [esi] == "."
inc Pointfound
.if Pointfound > 1
jmp FindeCertificationChiffre
.endif
.elseif byte ptr [esi] =="U"
inc Ufound
.if Ufound > 1
jmp FindeCertificationChiffre ;compiled allowed but function .. not ok ??????????
.endif
;it is a suffixe,only letter after ,max 2
.if byte ptr [esi + 1] != 0
.if byte ptr [esi + 1] == "L" || byte ptr [esi + 1] == "I"
;do nothing
.else
jmp FindeCertificationChiffre ;not a number
.endif
.endif
.elseif byte ptr [esi] == "L"
inc Lfound
.if Lfound > 2
jmp FindeCertificationChiffre ;not a number
.endif
.if Lfound == 2
.if byte ptr [esi-1] != "L"
jmp FindeCertificationChiffre ;not a number
.endif

.if byte ptr [esi+1] == 0 || byte ptr [esi+1] == "U"
;ne rien faire
.else
jmp FindeCertificationChiffre ;not a number
.endif
.endif
.if Lfound == 1
.if byte ptr [esi+1] == 0 || byte ptr [esi+1] == "L" || byte ptr [esi+1] == "U"
;do nothing
.else
jmp FindeCertificationChiffre ;not a number
.endif
.endif

.elseif byte ptr [esi] == "I"
inc Ifound
.if Ifound > 1
jmp FindeCertificationChiffre
.endif
.elseif byte ptr [esi] == "P"
inc Pfound
.if Pfound > 1
jmp FindeCertificationChiffre
.endif
;.FP only
.if  byte ptr [esi-1] == "F" && byte ptr [esi-2] == "."
;do nothing
.else
jmp FindeCertificationChiffre
.endif
.elseif byte ptr [esi] == "+"
inc Plusfound
.if Plusfound > 1 ;the first had been skipped
jmp FindeCertificationChiffre
.endif
.elseif byte ptr [esi] == "-"
inc Moinsfound
.if Moinsfound > 1 ;the first had been skipped
jmp FindeCertificationChiffre
.endif

.else
;not a number
jmp FindeCertificationChiffre
.endif
jmp loopnumber
.else
jmp loopnumber
.endif
.else
mov retour,1 ;it is a number
jmp FindeCertificationChiffre
.endif



mov retour,1
 FindeCertificationChiffre:
         mov eax,retour
mov edx,hexa
         ret
composition:
xor edx,edx
mov ecx,sizeof chiffrehexa ;tableau car hexa
.if base == hexadecimal
lea edi,chiffrehexa
.elseif base == decimal
lea edi,chiffredeci
.elseif base == octal
lea edi,chiffreoctal
.endif
repnz scasb
.if ecx != 0
mov edx,1
.endif
;chiffrehexa db "0","1","2","3","4","5","6","7","8","9","A","a","B","b","C","c","D","d","E","e","F","f",0
retn
CertificationChiffre endp
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

lit_test proc uses esi psz: ptr TCHAR


.if rv(CertificationChiffre,psz)
print "  valid: "
.else
print "invalid: "
.endif
print psz,13,10

ret

lit_test endp

main proc
comment µ
fn lit_test,"123"
fn lit_test,"123.456"
fn lit_test," 123"
fn lit_test," 123  "
fn lit_test," 123a"
fn lit_test," .123f"
fn lit_test," .123L "
fn lit_test,"123.456E+78"
fn lit_test,"-123"
fn lit_test,"  -123.  "
fn lit_test,"0x123"
fn lit_test,"  0x123  "
fn lit_test," 0x123."
fn lit_test," 0x123. "
fn lit_test," 0x12f.4f"
fn lit_test," 0xf123.fp+123"
fn lit_test," 0xf123.fp123"
fn lit_test," 0xf123.fp+123 "
fn lit_test," 0xf123.fp+123l "
fn lit_test," 0xf123.fp+123F"
fn lit_test," 01234567 "
fn lit_test," 012345677 "
fn lit_test," 0123456789"
fn lit_test," 0b1234567 "
fn lit_test," 0b1 "
fn lit_test," 0b"
fn lit_test," 0x"
fn lit_test," 0x0"
µ
fn lit_test," 0 "
fn lit_test,"0"
fn lit_test,"00"
fn lit_test,"1"
fn lit_test," 1"
fn lit_test," 1 "
fn lit_test,"0b101010111"
fn lit_test,"123."
fn lit_test,"0x.F"
fn lit_test,"0x.0p0"
fn lit_test,"1."
fn lit_test,"0.0"
fn lit_test,"0."
fn lit_test,".0"
fn lit_test,".0E-123"
fn lit_test,"1.0E0"
fn lit_test,"1.00E+0"
fn lit_test," +.0E0 "
fn lit_test," -0XFFFFFFFF "
fn lit_test," -0xffffffff "
fn lit_test,"0123"
fn lit_test,"0x.123p456-"
fn lit_test," 5555q"
fn lit_test," 123456ull "
fn lit_test," 0xff123ul "
fn lit_test," -0xff123lu "
fn lit_test,"0xff123llu "
fn lit_test,"123u"
fn lit_test,"456li"
fn lit_test,"0777777-"
fn lit_test," 0777E+3"
fn lit_test,"0123.456"
fn lit_test," 0x123fff.ffae"
fn lit_test,"0x123fff.ffae+23"
fn lit_test,"+9"
fn lit_test,"+666ull"
fn lit_test,"+666.000l"
fn lit_test,"  -  666.999e-666 "
fn lit_test," 123i64"
fn lit_test,"-123i32"
fn lit_test,"0x123fff.23u"
fn lit_test,"0x123fff.23i32"
fn lit_test,"0x123fffi32"
fn lit_test,"0x123fffi16"
fn lit_test,"0x123fffi8"
fn lit_test,"0x123fffi9"
fn lit_test,"0x123fffi64q"
fn lit_test,"0x123fffi8 asd"
fn lit_test,"00000.000002E-01"
fn lit_test," .000000E-01 "
fn lit_test,"0.01E-01"
fn lit_test,".9u"
fn lit_test,".E-1"

fn lit_test,"0x0"
fn lit_test,"0X245f"
fn lit_test,"0X245flu"
fn lit_test,"245u"
fn lit_test,"0x1df56bULL"
fn lit_test,"0x1df56bi64"
fn lit_test,"0.2E-01"
fn lit_test,"0.1"
fn lit_test,"0x7ffffffffi8"
fn lit_test,"0x7ffffffffI16"
fn lit_test,"0x7ffffffffI32"
fn lit_test,"0x7ffffffffI64"
fn lit_test,"0x7ffffffffuI32"
fn lit_test,"0756"
fn lit_test,"-1.18E - 38"
fn lit_test,"-1.18E-38"

inkey
exit
main endp
end main
« Last Edit: September 15, 2014, 04:10:53 AM by ToutEnMasm »
Fa is a musical note to play with CL

qWord

  • Member
  • *****
  • Posts: 1454
  • The base type of a type is the type itself
    • SmplMath macros
Re: is it a c++ number ?
« Reply #11 on: September 14, 2014, 10:12:37 PM »
Just a question,I don't see what is the masm equivalent to "0xf123.fp+123l" ?.
There is no direct equivalent thus conversion is needed. I would convert thus numbers to MASMs hexadecimal initializers (e.g. 3f800000r). However, the literals are only supported by C and not C++, so you might can simply drop the support for them.

I've seen that your above code must reworked because it:
 - does reject valid FP numbers starting with a dot (e.g. ".123")
 - accepts invalid octal numbers like "0123456789"
 - does not recognized the "u" for MSVC integer suffixes (e.g. "uI32")
 - accepts "0b", which is invalid
...
MREAL macros - when you need floating point arithmetic while assembling!

MichaelW

  • Global Moderator
  • Member
  • *****
  • Posts: 1209
Re: is it a c++ number ?
« Reply #12 on: September 14, 2014, 11:20:07 PM »
The attachment contains a recent adaptation of some old code that I use to verify that an input string, that is supposed to represent a double, is correctly formatted. For engineering calculations I need to guard against incorrectly formatted inputs because they are likely to contain errors, and the CRT conversion functions, because they stop the conversion at the first character that is not recognized as part of a valid number, will silently convert these inputs. It's straight C code, but seems fairly fast. In my tests, running on a Core-i3 and checking the string "123.456e3", I get 433 cycles without optimization and 302 with /O2 /G6.

My code handles doubles only, but I think the method could be easily adapted to integers, or even to ignore trash at the end of the string as the CRT does.

Edit: I missed an obvious optimization. For my work most of the pattern strings will be short, typically "dpd" independent of the number of decimal digits, so the code is faster if I define the valid patterns as:
Code: [Select]
    static char pats[18][7] = {"d","pd","sd","ded","dpd","spd","desd",
                               "pded","sded","sdpd","dpded","pdesd",
                               "sdesd","spded","dpdesd","spdesd",
                               "sdpded","sdpdesd"};

Updated the attachment.
« Last Edit: September 15, 2014, 02:13:10 AM by MichaelW »
Well Microsoft, here’s another nice mess you’ve gotten us into.

jj2007

  • Member
  • *****
  • Posts: 7548
  • Assembler is fun ;-)
    • MasmBasic
Re: is it a c++ number ?
« Reply #13 on: September 15, 2014, 12:06:01 AM »
- accepts invalid octal numbers like "0123456789"
..
 - accepts "0b", which is invalid

I saw that you reject the decimal string "0123456789" - why that? Also, 0b is valid in assembler, not so in C/C++?


qWord     string       MasmBasic
  valid:  012345677     valid
invalid:  0123456789    valid
invalid:  0b1234567     valid
  valid:  0b1   valid
invalid:  0b    valid
invalid:  0x    invalid
  valid:  0x0   valid


Note I am not saying your code is wrong - I am just curious.

qWord

  • Member
  • *****
  • Posts: 1454
  • The base type of a type is the type itself
    • SmplMath macros
Re: is it a c++ number ?
« Reply #14 on: September 15, 2014, 12:18:49 AM »
I saw that you reject the decimal string "0123456789" - why that? Also, 0b is valid in assembler, not so in C/C++?
C, C++ and Assembler are different languages and thus have different kind of literals/constants.
For C and C++, octal numbers (base 8 ) begins with a zero thus "0123456789" is invalid due to "89". "0b" is valid for MASM because "b" is a suffix, whereas it must be a prefix for C++14 (previous standards and C doesn't support binary literals btw). It is same as that "0x" is not a number.
MREAL macros - when you need floating point arithmetic while assembling!