The MASM Forum Archive 2004 to 2012

General Forums => The Laboratory => Topic started by: ecube on November 13, 2006, 03:01:29 PM

Title: wsprintf mini clone problems
Post by: ecube on November 13, 2006, 03:01:29 PM
I thought it to be rather ridicules that I kept using wsprintf to format some html text especially when it has that 1024 limit and I was only really using the %s delim, so I wrote this...it's over twice as fast as wsprintf but it doesn't work entirely so that doesn't say much. It only replaces the first instance of %s I can't figure out why.


.686
.model flat, stdcall
option casemap:none


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

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\user32.lib

wxprintf proto ,:dword, :dword,:dword, :dword,:dword, :dword,:dword, :dword,:dword,:dword

     CTEXT MACRO text:VARARG
            LOCAL TxtName
              .data
               TxtName BYTE text,0
              .code
            EXITM <ADDR TxtName>
     ENDM     

.code
start:
invoke wxprintf,addr szBuff,CTEXT("hey %s you %s?"),CTEXT("how are"),CTEXT("doing"),0,0,0,0,0,0
invoke ExitProcess,0

wxprintf proc iBuf,iSep,iData1,iData2,iData3,iData4,iData5,iData6,iData7,iData8
    mov edi, dword ptr [esp+8]
    mov esi, dword ptr [esp+12]
    mov edx,12
@Bx:
    cmp word ptr [esi],'s%'
    je @F
    mov al,byte ptr [esi]
    inc esi
    mov [edi], al
    inc edi
    test al, al
    jnz @Bx
    ret 8   
    @@:
    add edx,4
    mov ecx,dword ptr [esp+edx]
    @@:
    mov al,byte ptr [ecx]
    inc ecx
    mov [edi], al
    inc edi
    test al, al
    jnz @B
   add esi,2
    jmp @Bx
wxprintf endp
end start
Title: Re: wsprintf mini clone problems
Post by: Tedd on November 13, 2006, 03:24:27 PM
You're copying the null of the %s string, so what you end up with is:

"hey " + "how are",0 + " you " + "doing",0 + "?",0

then, of course, when you come to print it you only get to print upto the first null -- "hey how are"



Bonus points: change the function definition to "wxprintf proc C iBuf:DWORD,iSep:DWORD,iData:VARARG"
so you only need to give as many arguments as needed.
Title: Re: wsprintf mini clone problems
Post by: ecube on November 13, 2006, 08:54:14 PM
Thanks Tedd you're an all star :)
Heres the fixed version, but due note if you have more %s in your formatter than specified iData arguments you'll get unexpected results, but personally I always check, i'll probably write another version to error check unless someone else does. Also I attached files for speed testing it isn't working for my proc :(.

wxprintf proto C :dword, :dword,:VARARG

.code
wxprintf proc C iBuf,iSep,iData:VARARG
    mov edi, dword ptr [esp+8]
    mov esi, dword ptr [esp+12]
    mov edx,12
@Bx:
    cmp word ptr [esi],'s%'
    je @F
    mov al,byte ptr [esi]      
    inc esi   
    mov [edi], al   
    inc edi
    test al, al
    jnz @Bx
    ret 8   
    @@:
    add edx,4
    mov ecx,dword ptr [esp+edx]
    add esi,2
    @@:
    mov al,byte ptr [ecx]      
    test al, al
    jz @Bx
    inc ecx
    mov [edi], al
    inc edi   
    jmp @B   
wxprintf endp

[attachment deleted by admin]
Title: Re: wsprintf mini clone problems
Post by: Tedd on November 13, 2006, 09:04:29 PM
Easy mistake :wink
I don't think wsprintf checks for the number of parameters against % formatters either :bdg

If you want to get really fussy, since you're not using the stack-frame and are accessing parameters directly, you can turn off the ebp setup code (which is generated otherwise.) Can't remember the exact lines, but it's OPTION PROLOG:NONE and OPTION EPILOG:NONE (or something similar; should be easy enough to find out) and then turn it back on at the end of the function definition.
Title: Re: wsprintf mini clone problems
Post by: ecube on November 13, 2006, 09:23:51 PM

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
wxprintf proc C iBuf,iSep,iData:VARARG
    mov edi, dword ptr [esp+8]
    mov esi, dword ptr [esp+12]
    mov edx,12
@Bx:
    cmp word ptr [esi],'s%'
    je @F
    mov al,byte ptr [esi]     
    inc esi   
    mov [edi], al   
    inc edi
    test al, al
    jnz @Bx
    ret 8   
    @@:
    add edx,4
    mov ecx,dword ptr [esp+edx]
    add esi,2
    @@:
    mov al,byte ptr [ecx]     
    test al, al
    jz @Bx
    inc ecx
    mov [edi], al
    inc edi   
    jmp @B   
wxprintf endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


Thanks again you're a big help,do you have any idea why the speed testing isn't working? It just exits the program I really want to see how fast this thing is.

*updated source files to.

[attachment deleted by admin]
Title: Re: wsprintf mini clone problems
Post by: stanhebben on November 13, 2006, 10:34:30 PM
You have a little error in your code. At return, your popped 8 bytes off the stack.

So, change 'ret 8' so 'ret'. That will make it working.

I changed the test program a bit, so it runs in a console.

[attachment deleted by admin]
Title: Re: wsprintf mini clone problems
Post by: ecube on November 13, 2006, 10:43:57 PM
wsprintf 785
wxprintf 32


2543% as fast!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

*takes a bow
Title: Re: wsprintf mini clone problems
Post by: ecube on November 14, 2006, 02:18:55 AM
i'm working on a better replace function based off code above, it'll allow you to replace all the found instances of the search string with the replace string and neither of their sizes matter, one can be larger or shorter than the other, isn't quite working yet, but its close. Also its case sensitive for now, but you can use other procs to make both string upper/lower case prior to testing. And its fast! the other replace procedures i've seen in masm are long, slow, and bulky.
Title: Re: wsprintf mini clone problems
Post by: ecube on November 16, 2006, 07:24:42 AM
I tried optimizing the bit of code above and learned hutch-- was right about add/sec being faster than inc/dec on newer machines. Atleast on my  amd 64 3800 it was.