an equivalent of sprintf_s for masm

Started by ToutEnMasm, November 02, 2011, 04:24:55 PM

Previous topic - Next topic

ToutEnMasm

Here is a draft of code to made that. (he show the MEMORYSTATUSEX structure)
The part without float would be not very hard.
What i need is a function who convert floating point and who is a little improve.
Any help is welcome.
Quote
.NOLIST            
   include masm32rt.inc
   InitInstance PROTO :DWORD   
   ChiffreToascii PROTO  :DWORD,  :DWORD ,:DWORD
   
   .const
MEMORYSTATUSEX   STRUCT
   dwLength DWORD ?
   dwMemoryLoad DWORD ?
   ullTotalPhys QWORD ?
   ullAvailPhys QWORD ?
   ullTotalPageFile QWORD ?
   ullAvailPageFile QWORD ?
   ullTotalVirtual QWORD ?
   ullAvailVirtual QWORD ?
   ullAvailExtendedVirtual QWORD ?
MEMORYSTATUSEX      ENDS
Formatte PROTO C :DWORD,  :DWORD, :DWORD, :VARARG

   
   .data
hInstance dd 0
caption           db      "    MEMORYSTATUSEX   ",0
fmt               db      "dwMemoryLoad Percent memory in used   :",9,"%d",13,10 
         db      "ullTotalPhys total physical memory     :",9,"%I64Xh",13,10
         db      "ullAvailPhys free physical memory     :",9,"%I64Xh",13,10 
         db      "ullTotalPageFile total paging file     :",9,"%I64Xh",13,10
         db      "ullAvailPageFile free  paging file     :",9,"%I64Xh",13,10
         db      "ullTotalVirtual  total virtual memory     :",9,"%I64Xh",13,10
         db      "ullAvailVirtual  free  virtual memory     :",9,"%I64Xh",13,10
         db      "ullAvailExtendedVirtual:",9,"%I64Xh",13,10                                    
         db 13,10,0

memstat   MEMORYSTATUSEX <sizeof MEMORYSTATUSEX,,,,,,,,>
asciiz1               db      500 dup(?)
hextable BYTE "0123456789ABCDEF",0
Chiffre db 50 dup (0)
   
   .code
;not very fast but multi usage ,tested on the forum
;give better result than itoa
;################################################################
BaseN PROC uses esi edi ebx value:DWORD,  base:DWORD,  pout:DWORD
   mov ebx,0
   lea edi,Chiffre
   add edi,LENGTHOF Chiffre - 2
   lea esi,hextable   
   ;début
   mov eax,value
   mov ecx,base         ;975 = 9*10!2 + 7*10!1 + 5*10!0     10!0 = 1   
   newpowerofbase:         ; ! = power of         
   xor edx,edx
   div ecx            ;divide by the base!1 in loop
   ;le reste donne
   mov dl,[esi+edx]
   mov [edi],dl
   inc ebx
   .if eax != 0 ;dividend not null,use the next power of base
      ;ascii numbers are written right to left
      dec edi   ;pointer of ascii number -1      
      jmp newpowerofbase
   .endif
   mov esi,edi
   mov ecx,ebx
   inc ecx   ;add the zero
   mov edi,pout
   rep movsb
FindeBaseN:
   mov eax,ebx      ;return lenght of ascii chiffre without the zero
   ret
BaseN endp
;source=format
;dest = ascii nombre
;pointerarg = value binaire
;################################################################
ChiffreToascii PROC uses esi edi ebx source:DWORD,  dest:DWORD ,pointerarg:DWORD
   local lvalue:DWORD,hvalue
   local format[10]:byte   
   local awrite[20]:byte
   mov esi,source
   lea edi,format
   mov ebx,pointerarg
   inc esi   ;passe %
   @@:
   .if byte ptr [esi] > " "
      movsb
      jmp @B
   .endif
   mov byte ptr [edi],0
   ;sauvegarde esi
   mov source,esi
   ;-----------------
   lea esi,format
   mov edi,dest
   .if byte ptr [esi] == "d"
      ;argument dword
      mov eax,[ebx]
      mov lvalue,eax
      add ebx,4
      invoke BaseN,lvalue,10,dest
      add edi,eax
      
   .elseif byte ptr [esi] == "I"
      ;argument qword
      mov eax,[ebx]
      mov lvalue,eax
      add ebx,4
      mov eax,[ebx]
      mov hvalue,eax
      add ebx,4      
      invoke BaseN,hvalue,16,addr format; reutilise format
      push edi
      mov ecx,eax
      lea edi,awrite
      lea esi,format
      rep movsb
      mov byte ptr [edi],0
      invoke BaseN,lvalue,16,addr format
      lea esi,format      
      mov ecx,8
      sub ecx,eax
      push eax
      .if ecx != 0
         ;adj to 8 the lenght of loword
         mov al,"0"
         @@:
         stosb
         dec ecx
         jnz @B
      .endif
      pop ecx
      rep movsb
      mov byte ptr [edi],"h"
      inc edi
      mov byte ptr [edi],0
      pop edi
      lea esi,awrite
      @@:
      .if byte ptr [esi] != 0
         movsb
         jmp @B
      .endif
      mov byte ptr [edi],0
            
            
   .endif
   
FindeChiffreToascii:
   mov eax,source
   mov ecx,edi
   mov edx,ebx
         ret
ChiffreToascii endp

;################################################################
Formatte PROC C uses esi edi ebx buffer:DWORD,buffersize:DWORD,format:DWORD,arg:VARARG
         Local  retour:DWORD
         mov retour,1
   mov esi,format
   mov edi,buffer
   lea ebx,arg
   @@:
   .if byte ptr [esi] != 0 && byte ptr [esi] != "%"
      movsb
      jmp @B
   .endif
   .if byte ptr [esi] == "%"
      invoke ChiffreToascii,esi,edi,ebx
      mov edi,ecx
      mov esi,eax
      mov ebx,edx
      jmp @B
   .endif
   mov byte ptr [edi],0
FindeFormatte:
         mov eax,retour
         ret
Formatte endp

;################################################################

   
;################################################################
MemInfo PROC
      
invoke GlobalMemoryStatusEx,addr memstat

invoke Formatte,addr asciiz1,sizeof asciiz1,addr fmt,memstat.dwMemoryLoad,memstat.ullTotalPhys,
         memstat.ullAvailPhys,memstat.ullTotalPageFile,memstat.ullAvailPageFile,
         memstat.ullTotalVirtual,memstat.ullAvailVirtual,memstat.ullAvailExtendedVirtual,
         memstat.dwMemoryLoad
   

invoke MessageBox,0,addr asciiz1,addr caption,0                                             

FindeMemInfo:
         ret
MemInfo endp   

start:
   invoke GetModuleHandle,NULL
   mov hInstance,eax   
   invoke MemInfo
   invoke ExitProcess,0
   
end start


ToutEnMasm


Finally,the best equivalent of sprintf_s is sprintf_s loaded dynamically.
The code could be mixed with c++ and the size of the exe for this one is 4k (using link )
The msvcr100.dll could be not found on all the system.She have most of the last crt functions.
Quote
.NOLIST         ;signifie: ne rien mettre dans le listing   
   include masm32rt.inc
   InitInstance PROTO :DWORD   
   ChiffreToascii PROTO  :DWORD,  :DWORD ,:DWORD
   
   .const
MEMORYSTATUSEX   STRUCT
   dwLength DWORD ?
   dwMemoryLoad DWORD ?
   ullTotalPhys QWORD ?
   ullAvailPhys QWORD ?
   ullTotalPageFile QWORD ?
   ullAvailPageFile QWORD ?
   ullTotalVirtual QWORD ?
   ullAvailVirtual QWORD ?
   ullAvailExtendedVirtual QWORD ?
MEMORYSTATUSEX      ENDS
;sprintf_s PROTO C :DWORD ,:DWORD ,:DWORD , :VARARG

Psprintf_s TYPEDEF PROTO C :DWORD ,:DWORD ,:DWORD , :VARARG
Fsprintf_s TYPEDEF PTR Psprintf_s
sprintf_s TEXTEQU <Fsprintf_s ptr ADRsprintf_s>   
   .data
ADRsprintf_s dd 0
func_sprintf_s db "sprintf_s",0   
NomCrt db "msvcr100.dll",0
Hcrtdll dd 0
hInstance dd 0
caption           db      "    MEMORYSTATUSEX   ",0
fmt               db      "dwMemoryLoad Percent memory in used   :",9,"%d",13,10 
         db      "ullTotalPhys total physical memory     :",9,"%I64Xh",13,10
         db      "ullAvailPhys free physical memory     :",9,"%I64Xh",13,10 
         db      "ullTotalPageFile total paging file     :",9,"%I64Xh",13,10
         db      "ullAvailPageFile free  paging file     :",9,"%I64Xh",13,10
         db      "ullTotalVirtual  total virtual memory     :",9,"%I64Xh",13,10
         db      "ullAvailVirtual  free  virtual memory     :",9,"%I64Xh",13,10
         db      "ullAvailExtendedVirtual:",9,"%I64Xh",13,10                                    
         db 13,10,0

memstat   MEMORYSTATUSEX <sizeof MEMORYSTATUSEX,,,,,,,,>
asciiz1               db      500 dup(?)
hextable BYTE "0123456789ABCDEF",0
Chiffre db 50 dup (0)
   
   .code   
MemInfo PROC
      
invoke GlobalMemoryStatusEx,addr memstat

invoke sprintf_s,addr asciiz1,sizeof asciiz1,addr fmt,memstat.dwMemoryLoad,memstat.ullTotalPhys,
         memstat.ullAvailPhys,memstat.ullTotalPageFile,memstat.ullAvailPageFile,
         memstat.ullTotalVirtual,memstat.ullAvailVirtual,memstat.ullAvailExtendedVirtual,
         memstat.dwMemoryLoad
   

invoke MessageBox,0,addr asciiz1,addr caption,0                                             

FindeMemInfo:
         ret
MemInfo endp   

start:
   invoke GetModuleHandle,NULL
   mov hInstance,eax   
   invoke LoadLibrary,addr NomCrt
   mov Hcrtdll,eax
   .if eax != 0
      invoke GetProcAddress,Hcrtdll,addr func_sprintf_s
      mov ADRsprintf_s,eax
      .if eax != 0
         invoke MemInfo
      .endif
   .endif
   .if Hcrtdll != 0
      invoke FreeLibrary,Hcrtdll
   .endif
   invoke ExitProcess,0
   
end start

Vortex

Hi ToutEnMasm,

Why not to create an import library for msvcr100.dll ?

Vortex

Salut ToutEnMasm,

I tried Pelles static library crt.lib to eliminate the msvcr100.dll dependency but the final executable's size is 19 Kb  Creating your own functions in your first posting is the best approach in my opinion.



.386
.model flat,stdcall
option casemap:none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\user32.inc
include     \masm32\include\masm32.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\user32.lib
includelib  \masm32\lib\masm32.lib
includelib  \Pellesc\lib\crt.lib ; Pelles CRT static library

__ioinit    PROTO C :VARARG
__bheapinit PROTO C :VARARG
sprintf_s   PROTO C :DWORD,:DWORD,:VARARG

MAX_NUMB_OF_CHARS equ 64

.data

format1     db 'This is %s %d',0
arg1        db 'test',0

.data?

buffer      db MAX_NUMB_OF_CHARS dup(?)

.code

.code

start:

    invoke  __bheapinit ; The thread
    test    eax,eax     ; http://www.masm32.com/board/index.php?topic=2670.0
    jz      finish      ; explains why __bheapinit and __ioinit are used here
    invoke  __ioinit

    invoke  sprintf_s,ADDR buffer,MAX_NUMB_OF_CHARS,\
            ADDR format1,ADDR arg1,1

    invoke  StdOut,ADDR buffer

finish:

    invoke  ExitProcess,0

END start

ToutEnMasm

I will try to made the two.
An independant clone of the sprintf_s function,using the masm32 FloatToStr function.
And a dynamic library for the msvcr100.dll ,more usable than an include file(i will made a tool for that).

Vortex

Quote from: ToutEnMasm on November 06, 2011, 04:55:05 PM
I will try to made the two.
An independant clone of the sprintf_s function,using the masm32 FloatToStr function.
And a dynamic library for the msvcr100.dll ,more usable than an include file(i will made a tool for that).

Salut ToutEnMasm,

An independant function will be nice, thanks.

Attached is the revised example above linked with msvcr100.lib

jj2007

Quote from: ToutEnMasm on November 06, 2011, 04:55:05 PM
An independant clone of the sprintf_s function,using the masm32 FloatToStr function.
FloatToStr still has a little bug. MasmBasic Str$() has no crt dependency but its sprint_xx emulation is limited to %i, %f and %u. But then, there is no point in emulating the %s operator if you can use Print Str$("The number is %i", eax), ", and the string comes afterwards" ;-)

ToutEnMasm

Quote
FloatToStr still has a little bug

Thanks for information.I will change for FloatToStr2