上周我读了this answer及其附带的关于字符串的评论 逆转常规。 我决定自己测试一下,偶然发现一个明显的异常现象。 由于某种原因,第二个例程的表现取决于 字符串的长度是否短于128个字节。
UsingXchg UsingMov UsingBswap
add eax, ebx add eax, ebx mov edx, eax
jmp B jmp B add eax, ebx
A: mov dl, [ebx] A: mov dl, [ebx] jmp B
xchg dl, [eax] mov cl, [eax] A: sub eax, 4
mov [ebx], dl mov [eax], dl mov esi, [ebx]
inc ebx mov [ebx], cl mov edi, [eax]
B: dec eax inc ebx bswap esi
cmp ebx, eax B: dec eax bswap edi
jb A cmp ebx, eax mov [eax], esi
jb A mov [ebx], edi
add ebx, 4
B: sub edx, 8
jnb A
jmp D
On entry: EBX is address C: mov dl, [ebx]
EAX is length mov cl, [eax]
mov [eax], dl
mov [ebx], cl
inc ebx
D: dec eax
cmp ebx, eax
jb C
接下来的时间(以毫秒为单位)我测量了大量重复。
StringSize UsingXchg UsingMov UsingBswap
26 30.7 17.4 6.4
52 60.9 33.4 12.2
78 90.5 49.4 17.9
104 121.9 65.4 22.7
/------\
127 | 79.0 |
128 | 27.3 |
\------/
130 152.1 27.6 27.9
156 181.9 30.7 33.5
182 211.8 34.4 39.2
208 241.8 37.2 44.0
260 301.6 43.6 54.9
2600 2996.5 337.2 538.4
26000 29949.2 3226.5 5350.4
UsingXchg 和 UsingBswap 都显示规律性,但 UsingMov 清楚 在128字节标记处换档。 我怀疑缓存是这个小问题的核心,但是为什么不这样做 所有3个例程都显示相同的效果?
我想得出结论,最好的字符串反转例程是 UsingBswap 如果字符串超过127个字节,则使用旁路 这会是一个有效的结论吗?
mov edx, eax ;Remaining string length
add eax, ebx ;Turn EAX into a pointer
cmp edx, 127
ja D ;Don't use Bswap on long strings
jmp B
A: sub eax, 4
...
D: dec eax
cmp ebx, eax
jb C ;Still 2 bytes left