我想搜索一个汇编缓冲区,找到两个给定值之一,只有一位。让我们说0xfefefeff
和0xfefefefe
(换句话说 - 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
我尝试使用QueryPerformanceCounter
和visual studio diagnostic tools
__asm
片段中的C
片段来衡量执行时间,但无法找到一致的结果。这个问题的表现非常重要。
有什么想法可以更好地实现这一目标?
感谢。
答案 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方式”要快得多,仅此而已。