【发布时间】: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始终循环(无限循环),直到lodsb或scasb会因无效内存访问而崩溃……没有调试器?会很困难。 -
如果您希望这是半高效的,avoid the
loopinstruction 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