assembly 如何使用在线装配将字符串从源复制到目标?

kqqjbcuj  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(107)

我是汇编语言的新手,我试图将一个字符串从输入字符const char* source复制到输入参数char* destination中给定的另一个字符串中,我必须通过x86来实现,下面是我的代码:
注意:volatile标记变量/代码区域可以从外部源意外更改。

void samestring(const char* start, char* end) {
    asm volatile (
        "mov %[src], %%rsi\n"   
        "mov %[dest], %%rdi\n"  
        "xor %%al, %%al\n"      
          
        "inc %%rdi\n"           
        "cmpb $0, %%dl\n"       
        "jne copy_loop\n"       

        :                                                  
        : "memory", "%rsi", "%rdi", "%rax", "%rdx"          
        );
}

字符串
这是我从reddit上找到的关于类似问题的代码,由于我是汇编新手,我真的不知道这种方法是否有效,或者是否有方法可以改进这段代码,所以我想咨询汇编Maven,帮助告诉我我可以和应该在上面的代码中编辑什么,以减少时间消耗,
任何帮助都将不胜感激。

eagi6jfj

eagi6jfj1#

这是非常低效的,包括它将操作数放入asm语句的方式,以及循环本身一次复制1个字节。
如果您关心x86-64的效率,您应该使用SSE 2一次加载和检查16个字节,就像glibc为strcpy编写的手工asm一样。(或32字节的AVX 2)。https://codebrowser.dev/glibc/glibc/sysdeps/x86_64/strcpy.S.html-注意,它必须首先到达对准边界,例如检查指针不在页面的最后16个字节中,然后执行一个未对齐的vec,as with strlen
除非你优化的字符串长度可能是0到5个字节,而根本不关心长字符串的性能。使用AVX-512掩码存储(在Intel上高效,在AMD Zen 4上非常慢),向量可能是处理短字符串的有效方法,没有基于不同短长度的分支错误预测的风险,因为每个小于32字节的字符串都以相同的方式分支。

内联asm详情

这迫使编译器将指针存储到内存("m"约束),以便asm模板可以重新加载它们,而不是在"+S"(RSI)和"+D"(RDI)寄存器中请求它们,或者更好地是编译器选择的寄存器[src] "+r"(source)等。
它还无缘无故地无效地将AL归零,并且通过加载movb而不是movzbl (%[src]), %%edxHow to load a single byte from address in assembly)来对RDX具有虚假的依赖性。
test %dl, %dl是一种比cmpb $0, %dl更有效的设置FLAGS的方法。
除此之外,循环本身是幼稚的,但如果你想保持简单,作为一个初学者练习,一次只复制1个字节,也不算太坏。

相关问题