在装配中搜索2个不同值的最快方法

时间:2017-02-26 16:13:57

标签: c performance assembly x86

我想搜索一个汇编缓冲区,找到两个给定值之一,只有一位。让我们说0xfefefeff0xfefefefe(换句话说 - lsb对于搜索来说并不重要)

缓冲区的长度各不相同。

我想到了这项任务的两种可能方式:

方式#1:

mov eax, 0xfefefeff
test eax, eax
repne scasd
...
mov eax, 0xfefefefe
test eax, eax
repne scasd
方式#2:

mov eax, 0xfefefefe
lblSearch:
mov esi, [edi] ; edi - the buffer
and si, 0fffeh
cmp eax, esi
...
add edi, 4
loop lblSearch

我尝试使用QueryPerformanceCountervisual studio diagnostic tools __asm片段中的C片段来衡量执行时间,但无法找到一致的结果。这个问题的表现非常重要。

有什么想法可以更好地实现这一目标?

感谢。

1 个答案:

答案 0 :(得分:1)

以你的方式#2 and si,imm16是一个问题,它是部分16b写入esi然后下一个cmp eax,esi需要返回组合32b值,这将导致破坏注册别名和的依赖关系。

而不是and esi,0xfffffffe,它仅适用于esi,因此内部不需要别名/复制/撰写。

你可能想要展开它,特别是如果缓冲区的大小可以被一些不错的数字整除,否则做一些序言来对齐它。

不要使用loop,这是人为的慢。

另外,根据你在found / not_found案例中所做的事情,也可以在内部循环中编写没有分支的内容(例如,计算这些值的数量)。

所以#2重写方式:

    ; search for values 0xfefefefe and 0xfefefeff
    mov eax, 0xfefefefe
    mov edx, 0xfffffffe
    ; edi = buffer
    ; ecx = number of elements in buffer
lblSearch:
    mov esi, [edi] ; edi - the buffer
    add edi, 4
    and esi, edx
    cmp esi, eax
    jne lblNotFound
    ... one of values found
lblNotFound:
    dec ecx
    jnz lblSearch

这绝不是将其推向极限,因为您没有透露足够的信息。如果表现非常重要,可能值得展开这个等等。

甚至可以检查整体架构,看看是否有可能在制作人处捕获这些值,而不进行任何搜索。

这比你的“#2方式”要快得多,仅此而已。