News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

wsprintf mini clone problems

Started by ecube, November 13, 2006, 03:01:29 PM

Previous topic - Next topic

ecube

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

Tedd

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.
No snowflake in an avalanche feels responsible.

ecube

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]

Tedd

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.
No snowflake in an avalanche feels responsible.

ecube


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]

stanhebben

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]

ecube

wsprintf 785
wxprintf 32


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

*takes a bow

ecube

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.

ecube

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.