String 字符串反转函数x86 NASM程序集
我正在尝试编写一个函数,该函数使用x86 NASM汇编语言反转字符串中的字符顺序。我试着使用寄存器(我知道使用堆栈更有效),但我一直遇到分段错误,c声明如下String 字符串反转函数x86 NASM程序集,string,x86,nasm,String,X86,Nasm,我正在尝试编写一个函数,该函数使用x86 NASM汇编语言反转字符串中的字符顺序。我试着使用寄存器(我知道使用堆栈更有效),但我一直遇到分段错误,c声明如下 extern char* reverse(char*); 大会部分: section .text global reverse reverse: push ebp ; prologue mov ebp, esp mov eax, [ebp+8] ; ea
extern char* reverse(char*);
大会部分:
section .text
global reverse
reverse:
push ebp ; prologue
mov ebp, esp
mov eax, [ebp+8] ; eax <- points to string
mov edx, eax
look_for_last:
mov ch, [edx] ; put char from edx in ch
inc edx
test ch, ch
jnz look_for_last ; if char != 0 loop
sub edx, 2 ; found last
swap: ; eax = first, edx = last (characters in string)
test eax, edx
jg end ; if eax > edx reverse is done
mov cl, [eax] ; put char from eax in cl
mov ch, [edx] ; put char from edx in ch
mov [edx], cl ; put cl in edx
mov [eax], ch ; put ch in eax
inc eax
dec edx
jmp swap
end:
mov eax, [ebp+8] ; move char pointer to eax (func return)
pop ebp ; epilogue
ret
为什么会这样?在我的理解中,eax从不超出字符串的界限,所以[eax]中总是有一些东西。我怎么会出现分段错误?好吧,我弄明白了,我错误地使用了
测试eax,edx
而不是我应该使用的cmp eax,edx
。它现在可以工作了。我知道使用堆栈更有效不,它不是!就地反转比对字符串的每一个字节执行4字节的push
更有效。您的具体实现没有得到优化,但可能仍然更快。(例如,您不使用bswap
一次反转4个字节,在某些CPU(AMD)上,单独写入cl和ch将对ECX和循环结构产生错误依赖)。当然,您也可以使用SIMD forstrlen
(您称之为查找最后一个)使用SSE2一次反转16个字节,或者至少是一次4字节的比特黑客。在您开始交换之前就必须完成这项工作会让一些人感到痛苦,而push/pop实现可以同时完成这项工作。但是push/pop也需要两个循环,它们都可以复制和触摸5倍于只读和就地循环的内存。如果您要倒进一个大的bufAnyway,您甚至可以跳过strlen,使用SSSE3 forpshufb
您可以在现代x86 CPU上每时钟周期倒16字节,而您的CPU为1字节。我不认为AVX2会有帮助,直到冰湖;其他CPU将成为洗牌吞吐量的瓶颈。不过,IceLake上的AVX512VBMIvpermb
还是不错的:一次64字节的单uop。另请参见-GCC在自动矢量化单词(akashort
)反向循环中错过了优化。(我知道这比您可能已经准备好消化的优化更多,但其中一些可能会很有趣。另请参见其他指南、文档和性能链接。)
mov cl, [eax]