I have problems with Instring proc.I have a table named conv and string szString.I want to take each char and look on this table if they are on table store it if not skip to next char.I have tried below code but it crashes does anyone have a idea ?I have searched examples of it in masm32 dir and found one example in COM dir and Ernie says " invoke InString, 1, pszToken, ADDR szBuffer ; === has bug preserving regs" Here is my non working code charecter

.data?
bfkey dd ?
.data
conv db "ABCDEF0123456789"


     lea esi, szString
     lea edi, szStore
conv1:
     movzx edx, byte ptr 
     mov ,edx
     invoke InString,1,ADDR conv,addr bfkey
     test eax,eax
     jz  notpresent
     movzx ecx, byte ptr 
     mov byte ptr ,cl
     inc esi 
     inc edi

notpresent:
     cmp byte ptr ,0
     jnz conv1
     mov byte ptr,0
Thanks.
Posted on 2001-06-28 20:02:00 by LaptoniC
do a search for instring on this message board. you will find that some other people were having crashing problems too. click here for a related post smurf This message was edited by smurf, on 6/28/2001 9:52:22 PM
Posted on 2001-06-28 21:48:00 by smurf
I have posted this version before, the original InString proc had been changed too many times and it had a difficult to find bug in it that no-one could document so I rewrote it from scratch. Use this algo instead of the library version, it will replace the old one in the next update of the MASM32 library.

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

Istring proc startpos:DWORD,lpSource:DWORD,lpPattern:DWORD

    LOCAL sLen:DWORD
    LOCAL pLen:DWORD

    push ebx
    push esi
    push edi

    invoke lnstr,lpSource
    mov sLen, eax           ; source length
    invoke lnstr,lpPattern
    mov pLen, eax           ; pattern length

    cmp startpos, 1
    jge @F
    mov eax, -2
    jmp isOut               ; exit if startpos not 1 or greater
  @@:

    dec startpos            ; correct from 1 to 0 based index

    cmp  eax, sLen
    jl @F
    mov eax, -1
    jmp isOut               ; exit if pattern longer than source
  @@:

    sub sLen, eax           ; don't read past string end
    inc sLen
    mov ebx, sLen

    cmp ebx, startpos
    jg @F
    mov eax, -2
    jmp isOut               ; exit if startpos is past end
  @@:

    mov esi, lpSource
    mov edi, lpPattern
    mov al,            ; get 1st char in pattern
    xor ecx, ecx

    add ecx, startpos       ; add starting offset

    jmp Loop_Start

  ; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  Pre_Loop:
    pop ecx                 ; restore ECX
    inc ecx                 ; start on next byte

  Loop_Start:
    cmp al, 
    je Pre_Sub
    inc ecx
    cmp ecx, ebx
    jne Loop_Start

    jmp No_Match

  Pre_Sub:
    push ecx                ; preserve ECX
    mov edx, pLen
    mov edi, lpPattern

  Sub_Loop:
    mov ah, 
    cmp ah, 
    jne Pre_Loop            ; jump back on mismatch
    inc ecx
    inc edi
    dec edx
    jnz Sub_Loop            ; fall through if match

    pop ecx                 ; restore ECX
    mov eax, ecx            ; match
    inc eax
    jmp isOut
    
  ; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  No_Match:
    mov eax, 0

  isOut:

    pop edi
    pop esi
    pop ebx

    ret

Istring endp

; ########################################################################
Regards, hutch@pbq.com.au
Posted on 2001-06-28 22:13:00 by hutch--
Two points: 1) conv isn't null terminated. 2) you don't inc esi unless you match! Once you reach a character that is not in the string, you will sit in an endless loop. Mirno
Posted on 2001-06-29 05:34:00 by Mirno
I have changed my code like below but it still crashes.:(

.data
bfkey dd 0
conv  db "ABCDEF0123456789"


     lea esi, szString
     lea edi, szStore
conv1:
     movzx edx, byte ptr 
     mov ,edx
     invoke InString,1,ADDR conv,addr bfkey
     test eax,eax
     jz  notpresent
     movzx ecx, byte ptr 
     mov byte ptr ,cl
     

notpresent:
     inc esi 
     inc edi
     cmp byte ptr ,0
     jnz conv1
     mov byte ptr,0

invoke	SetDlgItemTextA, _hWin, EDIT_KEY, edi
Posted on 2001-06-29 12:11:00 by LaptoniC
Two more things (shouldn't fix the crashing): 1) You must only increment edi when it is present (otherwise you'll get holes in the output), but increment esi no matter what! 2) When you invoke SetDlgItemText you do so with edi pointing at the end (the null terminator) of your stored string! This shouldn't fix the crashing though! Can you find out where it is crashing in the exe? Are you sure it is in that function, or is it in the InString itself? Could it even be something like you've stored the strings in the code section, and it is read only? Mirno
Posted on 2001-06-29 12:39:00 by Mirno
LaptoniC, U can try this1
.data

;bfkey dd 0
;conv  db "ABCDEF0123456789"

szString db "Blah, 23424bla",0
szStore  db 20 dup (0)
Groups   dd "A","F"      ; 1st group -> "A" to "F"
         dd "0","9"      ; 2nd group -> "0" to "9"
;        .....           ;
;        .....           ; N group -> ...		
nGroups  dd 2            ; Number of Groups 

.code
        push    esi             ; save some registers
        push    edi             ;
        push    ebx             ;
        push    ebp             ;
        lea     esi,Groups      ;
        mov     edx,nGroups     ;
        lea     ebx,szStore     ;
        lea     edi,szString    ;
        push    ebx             ; save -> szStore
        xor     eax, eax        ;
        jz      Loop2           ; jmp to Loop2
NotPresent:                     ;
        inc     ecx             ;
        cmp     ecx, edx        ; edx= nGroups
        jnl     Loop2           ;
Loop1:                          ;
        push    edx             ; save  edx= nGroups
        mov     ebp, ;
        mov     edx,;
        sub     ebp,eax         ;
        sub     edx,eax         ;
        xor     ebp,edx         ; check sign  
        pop     edx             ; restore  edx= nGroups
        jns     NotPresent      ;
        mov     ,al        ; ebx->szStore
        inc     ebx             ;
Loop2:                          ;
        xor     ecx, ecx        ; reset index
        mov     al,        ; edi->szString
        inc     edi             ;
        test    eax,eax         ; end of szString ?
        jnz     Loop1           ;
        mov     ,al        ; ebx->szStore -> zero end
        pop     edx             ; restore  -> szStore for SetDlgItemTextA
        pop     ebp             ; restore some registers
        pop     ebx             ;
        pop     edi             ;
        pop     esi             ;


	invoke	SetDlgItemTextA, _hWin, EDIT_KEY, edx 
Posted on 2001-06-29 17:54:00 by buliaNaza
Thanks for the help. buliaNaza; Is your code only applicable to ABCDEF1234567890 or can it be applied to string like "XB901QKMWSTY" ? and how ? I have found the bugs in my code.Main bug resides in Instring proc.

conv1:
     movzx edx, byte ptr 
     mov ,edx
     push esi   ;if you dont save them they change :(
     push edi   
     invoke InString,1,ADDR conv,addr bfkey
     pop edi
     pop esi
      test eax,eax
     jz  notpresent
     mov al, byte ptr
     mov byte ptr ,al
     inc edi
notpresent:
     inc esi 
     cmp byte ptr ,0
     jnz conv1
     mov byte ptr ,0
invoke   SetDlgItemTextA, _hWin, EDIT_KEY, addr szStore
Posted on 2001-06-29 18:26:00 by LaptoniC
LaptoniC, I'm sorry! I don't test my proggi and I have some errors....


1.      mov     ebp, ;  wrong
        mov     edx,; wrong

        mov     ebp, ;  correct
        mov     edx,; correct

2.       Groups   dd "@","G"      ; 1st group -> "A" to "F"
				                      ; (@ is prev for "A", "G" is next for "F"   
                  dd 2Fh, 3Ah     ; 2nd group -> "0" to "9"
	                    			  ; (2Fh is prev for "0", 3Ah is next for "9"   

 

Example:
 1. "X B 901QKM W ST Y" -> "B WXY 01 9 Q K M" -> 7 groups

Groups            dd "A","C"      ; 1st group -> "B"
				                      ; ("A" is prev for "B", "C" is next for "B"   
                  dd  "V","Z"     ; 2nd group -> "W" to "Y"
				                      ; ("V" is prev for "W", "Z" is next for "Y"   
                   .........
                   .........
     
nGroups           dd 7            ; Number of Groups 
Posted on 2001-06-29 19:29:00 by buliaNaza
Is your proc just find if desired substring in string or give its position also.As far as I understood, in your code you mix the order of my conv.Sorry I am newbie
Posted on 2001-06-29 20:16:00 by LaptoniC
LaptoniC,
I have a table named conv and string szString.I want to take each char and look on this table if they are on table store it if not skip to next char.
The "right" usage of Instring proc is to search a phrase, "Sunday" as example, rather 1 byte, "9" as example, in a buffer with bytes to be searched through.. So, U don't need to look for substring in string and/or its position cos it is bit more slowly.. U want to rewrite "correct" bytes only from the string (szString) to new location (szStore). "Correct" bytes are from table conv. Plz, read the topic "Test a value inside a range" in Algorithms to learn more about my proc... Example Continued:


 1. "X B 901QKM W ST Y" -> "B WXY 01 9 Q K M" -> 7 groups

Groups            dd "A","C"      ; 1st group -> "B"
                                  ; ("A" is prev for "B", "C" is next for "B"   
                  dd  "V","Z"     ; 2nd group -> "W" to "Y"
	                               ; ("V" is prev for "W", "Z" is next for "Y"
                  dd  2Fh,"2"     ; 3rd group -> "0" to "1"
                                  ; (2Fh is prev for "0", "2" is next for "1"
                  dd  "8",3Ah     ; 4th group -> "9"
                                  ; ("8" is prev for "9", 3Ah is next for "9"
                  dd  "P","R"     ; 5th group -> "Q"
                                  ; ("P" is prev for "Q", "R" is next for "Q"
                  dd  "J","L"     ; 6th group -> "K"
                                  ; ("J" is prev for "K", "L" is next for "K"
                  dd  "L","N"     ; 6th group -> "K"
                                  ; ("L" is prev for "M", "N" is next for "M"
nGroups           dd 7            ; Number of Groups 
Posted on 2001-06-29 21:16:00 by buliaNaza
Thanks for the help.As you have asaid because I am scanning just one byte using Instring is time consuming.I have found a instruction repnz scasb.Can anyone give me an example for this.I learned that it scans byte in eax in edi? for ecx times..Should I pass every char one by one and increment at every loop or is there any simple way for this.
Posted on 2001-07-01 07:26:00 by LaptoniC
LaptoniC, What I don't properly understand is what you are trying to do with the BYTE sequence. Scanning a a byte sequence for a set of seperate characters is not that hard to do but I need some idea of what you want to do with it. You are better to use later type instructions as they are faster and cleaner code, You can scan for 1 or more bytes by using code like,

    mov al, 
    inc esi
and either scan the source a lot of times or test each character a lot of times. Just let us know what you are trying to do and probably someone can help you. Regards, hutch@pbq.com.au
Posted on 2001-07-01 08:46:00 by hutch--
Of course I can take a char one by one and compare it.However I just want to learn this scasb instruction.I saw in my asm book that repnz scasb is being used.I want to type less code.I saw some scanning function which uses repnz scasb and loadsb but I forgot where I saw and I didnt understood it.Thanks.
Posted on 2001-07-01 16:40:00 by LaptoniC
LaptoniC, here is an example that searches for the DWORD 'A' to 'E' that is passed to the PROC:

   .CONST

cSearch DWORD 'A',
              'B',
              'C',
              'D',
              'E'

        DWORD It_was_an_A,
              It_was_an_B,
              It_was_an_C,
              It_was_an_D,
              It_was_an_E

   .CODE

cSearchCode PROC xChar:DWORD
  push edi ;just so that windows will like us.
  mov eax,xChar
  mov edi,OFFSET cSearch ;address of string to search
  mov ecx,LENGTHOF cSearch ;number of elements to look through

  repne scasd
;Did we exit because of a match?
  jne  Return
;EDI points to the value after the one that was equal!
  call DWORD PTR 

Return:
  pop edi ;the things we do for windows... :)
  ret

cSearchCode ENDP

;These have to be outside the PROC because 'ret' means something
;different inside the PROC.
It_was_an_A:
  ret
It_was_an_B:
  ret
It_was_an_C:
  ret
It_was_an_D:
  ret
It_was_an_E:
  ret
...example of it's use:

    mov eax, 'A'
;execute the code for an 'A'
    invoke cSearchCode, eax
This message was edited by bitRAKE, on 7/1/2001 7:35:58 PM
Posted on 2001-07-01 19:23:00 by bitRAKE