1

I've been meaning to code a program which gets each character of a string and compare it with each character of another string. It basically counts the instances of the said character in the other string.

My problem is it does not seem to work on the second character onwards of the first string. Either I get a seg fault or the count equates to 0.

Any help would be appreciated. Thank you so much!

    mov ecx, [len2]             ; length of name2
    mov esi, name1
    mov edi, name2

    mov byte[count], 0          ; counts instance
    cld

    loop1:
        lodsb                   ; loads letter in name1
        loop2:
            cmp ecx, 0
            jne cont1

            mov ecx, [len2]     
            loop loop1

            cont1:
                scasb           ; compares character in al to every char in name2
                jne cont2

                inc byte[count]
            cont2:
                loop loop2
the.nnah
  • 11
  • 3
  • 2
    This code would do `scasb` `[len2]` times and continue with next instruction after `loop loop2`, which is not in question, so it's not clear how it would even get to `lodsb` second time or even loop through `name1`. Also it's not clear how long you want to loop through `name1`, if the `cmp ecx,0` would had chance to catch zero in `ecx` (it will not, because `loop loop2` will not jump when `--ecx == 0`), it will restore it to `[len2]` again, so that `loop loop1` would loop always (infinite loop), until `lodsb` or `scasb` would crash on invalid memory access... no debugger? Difficult will be. – Ped7g Oct 31 '17 at 15:36
  • 1
    If you want this to be semi-efficient, [avoid the `loop` instruction for looping](https://stackoverflow.com/questions/35742570/why-is-the-loop-instruction-slow-couldnt-intel-have-implemented-it-efficiently), and don't keep your loop counter in memory. You have lots of registers you aren't using, including `ebx`. – Peter Cordes Oct 31 '17 at 17:29
  • If you want to be *actually* efficient, figure out how to check each character you load against *multiple* characters from the set you're checking for. Like maybe multiply by `0x01010101` to broadcast it, then you can check for matches against 4 bytes at once. (xor and use the check-for-any-zero-byte bithack. https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord.) Or better, use SSE2 or SSE4.2. SSE4.2 pcmpistri is actually good for this kind of problem; you can use it to check 16 bytes for matches against 16 candidates at once. https://www.strchr.com/strcmp_and_strlen_using_sse_4.2 – Peter Cordes Oct 31 '17 at 17:34
  • BTW, the C standard library functions [`strspn`](http://en.cppreference.com/w/cpp/string/byte/strspn) / `strcspn` do this. You'll probably find optimized asm implementations of it if you search. e.g. the glibc source https://code.woboq.org/userspace/glibc/sysdeps/i386/strspn.S.html makes a lookup table of 256 bytes so it can do a lookup for each character to decide whether to stop or not. – Peter Cordes Oct 31 '17 at 17:46

1 Answers1

0
cmp ecx, 0
jne cont1

Why would you keep testing if the 2nd string if empty? Do it once and once only.

mov ecx, [len2]     
loop loop1

This pair of instructions is out of place. Needs to be after you made a complete run through the 2nd string.

Next is an improved version:

    mov  byte[count], 0 ; counts instance
    cmp  dword[len2], 0 ; length of name2
    je   EndIt
    mov  esi, name1
    mov  edi, name2
    cld
loop1:
    lodsb                 ; loads letter in name1
    mov  ecx, [len2]     
loop2:
    scasb                 ; compares character in al to every char in name2
    jne  NotEQ
    inc  byte[count]
  NotEQ:
    dec  ecx
    jnz  loop2
    jmp  loop1
EndIt:

What's still missing here is how you will stop the outer loop.

Perhaps your 1st string uses zero termination?

    lodsb                 ; loads letter in name1
    cmp  al, 0
    je   EndIt
Sep Roland
  • 33,889
  • 7
  • 43
  • 76