【问题标题】:How to search each character of a string to another string in Assembly如何在Assembly中将字符串的每个字符搜索到另一个字符串
【发布时间】:2018-04-12 19:54:39
【问题描述】:

我一直想编写一个程序来获取字符串的每个字符并将其与另一个字符串的每个字符进行比较。它基本上计算另一个字符串中所述字符的实例。

我的问题是它似乎不适用于第一个字符串之后的第二个字符。要么我得到一个段错误,要么 count 等于 0。

任何帮助将不胜感激。太感谢了!

    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

【问题讨论】:

  • 这段代码会执行scasb [len2] 次,并在loop loop2 之后继续执行下一条指令,这是没有问题的,所以不清楚它如何第二次到达lodsb甚至循环通过name1。也不清楚你想循环通过name1 多长时间,如果cmp ecx,0 有机会在ecx 中捕获零(它不会,因为loop loop2 不会在--ecx == 0 时跳转),它会再次将其恢复为[len2],以便loop loop1 始终循环(无限循环),直到lodsbscasb 会因无效内存访问而崩溃……没有调试器?会很困难。
  • 如果您希望这是半高效的,avoid the loop instruction for looping,并且不要将循环计数器保存在内存中。您有很多未使用的寄存器,包括ebx
  • 如果你想真正地​​高效,弄清楚如何检查你加载的每个字符与你正在检查的集合中的多个字符.就像可能乘以 0x01010101 来广播它,然后您可以一次检查 4 个字节的匹配项。 (异或并使用 check-for-any-zero-byte bithack。graphics.stanford.edu/~seander/bithacks.html#ZeroInWord.)或者更好的是,使用 SSE2 或 SSE4.2。 SSE4.2 pcmpistri 对这类问题其实很好;您可以使用它一次检查 16 个字节与 16 个候选人的匹配。 strchr.com/strcmp_and_strlen_using_sse_4.2
  • 顺便说一句,C 标准库函数 strspn / strcspn 就是这样做的。如果您搜索,您可能会找到它的优化 asm 实现。例如glibc 源代码code.woboq.org/userspace/glibc/sysdeps/i386/strspn.S.html 制作了一个 256 字节的查找表,因此它可以查找每个字符来决定是否停止。

标签: string loops assembly nasm


【解决方案1】:
cmp ecx, 0
jne cont1

如果第二个字符串为空,为什么还要继续测试?只做一次。

mov ecx, [len2]     
loop loop1

这对指令不合适。需要在你完成第二个字符串之后。

接下来是改进版:

    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:

这里仍然缺少的是如何停止外循环。

也许您的第一个字符串使用零终止符?

    lodsb                 ; loads letter in name1
    cmp  al, 0
    je   EndIt

【讨论】:

    猜你喜欢
    • 2021-11-28
    • 2013-01-18
    • 1970-01-01
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    相关资源
    最近更新 更多