News:

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

removing commas from a string?

Started by jckl, March 05, 2006, 04:43:11 AM

Previous topic - Next topic

jj2007

Quote from: usafman2006 on October 21, 2011, 03:48:03 PM
on a side note, anyone know how to concatenate strings together?

I normally use Let esi="First string "+offset String2+" third string" ;-)

If you prefer it hand-made:
- put edi to the end of the first string
- put esi to the start of the second one
- mov ecx, len(second string)
- rep movsb

dedndave

there is no need to concatonate the strings in this case
change the strings to
String1 byte 'The string "',0
String2 byte '" is',0
String3 byte ' not',0
String4 byte ' a palindrome.',13,10,0


1) display String1
2) display the variable palindrome string
3) display String2
4) if it is not a palindrome, display String3 - otherwise, skip this step
5) display String4

ToutEnMasm


invoke lstrcat,addr chaine,addr chaine1      ;zero terminate
invoke lstrcat,addr chaine,addr chaine2      ;and so on

usafman2006

For this program, I have to concatenate the three strings together and call the printstring procedure only 1 times to print out the entire sentence.  I'm getting closer to figuring it out though; thanks for all the help!

dedndave

well -
Jochen is showing you a method using MasmBasic
Yves is showing you a method using Masm32
:P

the instructions you want to learn about are refered to as the "string" instructions
MOVS - move string - moves a value from [ESI] to [EDI]
SCAS - scan string - compares values in AL/AX/EAX with the value at [EDI]
CMPS - compare string - compares the value at [ESI] with the value at [EDI]
STOS - store string - stores the value in AL/AX/EAX to [EDI]
LODS - load string - loads the value at [ESI] into AL/AX/EAX

they each come in different sizes
for example, MOVS can be used in different forms
        movsb    ;byte
        movsw    ;word
        movsd    ;dword


they can also be used with a label that infers the size
the assembler will choose the correct opcode, based on how the label is defined
if String1 is defined as a byte array...
        movs    String1
the assembler uses MOVSB

SCAS, STOS, and LODS use the AL, AX, or EAX register

the instructions use ESI and EDI as source and destination indexes (addresses)
MOVS and CMPS use both ESI and EDI
SCAS and STOS use EDI only
LODS uses ESI only

any of the string instructions may be combined with a REP prefix to cause repeat operations
the number of iterations is controlled by the count in ECX

the REP mneumonic is used with MOVS and STOS
REPZ or REPNZ are used with CMPS and SCAS
REP is not typically used with the LODS instruction, as it makes no sense to repeatedly load AL with a byte   :P

REPZ (or REPE) repeats while the result of the compare or scan is zero, or until the count in ECX expires
REPNZ (or REPNE) repeats while the result of the compare or scan is not zero, or until the count in ECX expires

for all the string instructions, the addresses in ESI and/or EDI are incremented or decremented according to size
for example, if MOVSD is used, both ESI and EDI are incremented or decremented by 4 as each dword is moved
the direction flag is used to control direction
CLD - clears the direction flag (up)
STD - sets the direction flag (down)

dedndave

now - for your specific case
you can create an empty buffer and copy each string into it by using MOVSB
to copy the constant strings, you can use SIZEOF String1-1 as the count (ECX)
we use -1 because we do not want to copy the 0 terminator

for the palindrome string, you can use the StrLen proc to get the size

        .DATA

String1 byte 'The string "',0
String2 byte '" is',0
String3 byte ' not',0
String4 byte ' a palindrome.',13,10,0

        .DATA?

Buffer db 256 dupp(?)

        .CODE

        cld
        mov     edi,offset Buffer

        mov     esi,offset String1
        mov     ecx,sizeof String1-1
        rep     movsb

        mov     edx,offset Target
        call    StrLen
        mov     esi,edx
        rep     movsb

        mov     esi,offset String2
        mov     ecx,sizeof String2-1
        rep     movsb

;test for palindrome=true here - if so, jump to SkipNot

        mov     esi,offset String3
        mov     ecx,sizeof String3-1
        rep     movsb

SkipNot:
        mov     esi,offset String4
        mov     ecx,sizeof String4-1
        rep     movsb

        mov byte ptr [edi],0          ;terminate the string
        mov     edx,offset Buffer
        call    WriteString

dedndave

of course, there is almost always a simpler way   :8)
it just may not be as fast...

;---------------------------------

PutStr  PROC

        push    eax
        jmp short PutSt1

PutSt0: inc     ecx
        inc     edx

PutSt1: mov     al,[ecx]
        mov     [edx],al
        or      al,al
        jnz     PutSt0

        dec     edx
        pop     eax
        ret

PutStr  ENDP

;---------------------------------

;
;
;
        mov     edx,offset Buffer

        mov     ecx,offset String1
        call    PutStr

        mov     ecx,offset Target
        call    PutStr

        mov     ecx,offset String2
        call    PutStr

;test for palindrome=true here - if so, jump to SkipNot

        mov     ecx,offset String3
        call    PutStr

SkipNot:
        mov     ecx,offset String4
        call    PutStr

        mov     edx,offset Buffer
        call    WriteString



usafman2006

curious, where do you have your StrLen storing it's value?  I have mine being stored in a variable I created in the data segment.  When I try to copy that value into the ecx register, the program crashes.  Any ideas?

dedndave

sorry about that   :red
i was refering to the routines i posted in this thread...
http://www.masm32.com/board/index.php?topic=17557.msg148015#msg148015

the length is returned in the ECX register, where it is convenient for other operations

;-----------------------------------------------------------

StrLen  PROC

;Call With: EDX = address of string
;
;  Returns: ECX = length of string

        PUSH    EAX
        PUSH    EDI
        MOV     AL, 0
        MOV     EDI, EDX
        MOV     ECX, 0FFFFFFFFh
        REPNZ   SCASB
        NEG     ECX
        SUB     ECX,2
        POP     EDI
        POP     EAX
        RET

StrLen  ENDP

;-----------------------------------------------------------


i didn't put any such comments in the PutStr routine
but, it does not preserve ECX (not needed) and it returns EDX pointing to the new null terminator
this is handy for the next PutStr operation

also, notice that the routines preserve EAX
this is not normal win32 behaviour, but it is compatible with Kip Irvine's libraries
you could use EAX to hold a value indicating whether or not the string is a palindrome

dedndave

i wrote a similar routine (posted somewhere) that returns the value in EAX
that is more or less how things are normally done in win32 - the result is in EAX
however, i modified this approach to "act more like what Kip would do"   :P

usafman2006