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
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
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 ; ########################################################################
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
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
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
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
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
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
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
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
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.
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,
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, email@example.com
mov al, inc esi
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.
LaptoniC, here is an example that searches for the DWORD 'A' to 'E' that is passed to the PROC:
...example of it's use:
.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
This message was edited by bitRAKE, on 7/1/2001 7:35:58 PM
mov eax, 'A' ;execute the code for an 'A' invoke cSearchCode, eax