XOR 64位中的所有字节以更少的指令进行寄存



假设在某个x86-64平台上,我们在某个64位寄存器中存储了一些64位值(让它成为RAX(。挑战在于在更少的指令调用中对所有初始值字节进行异或运算(将结果存储在哪里并不重要(。这是我的 8 条指令解决方案(在 NASM 中(:

mov    rbx, rax
bswap  rbx
xor    eax, ebx
mov    ebx, eax
bswap  ebx
xor    ax, bx
mov    bx, ax
xor    al, bh

我在ASM编程方面不是很有经验,所以也许你们在指令量方面有一些更好的解决方案。谢谢!

这个怎么样?

        movq xmm0,rax
        pclmullqlqdq xmm0,[mask]
        pextrb eax,xmm0,7

mask    dq 0101010101010101h, 0

这使用无进位乘法pclmullqlqdq在一个指令中完成所有异值。 最后一条指令提取累积的结果并将其存储到 al 中。

这是

支持System V x86_64 ABI(即可以直接从64b linux等中的C/C++调用(,5条指令(16字节((ret排除(。

; input: rdi = 8x packed byte, output al = xorred value
xorAllRdiBytes:
    shld    rax, rdi, 32
    xor     eax, edi
    shld    edi, eax, 16
    xor     ax, di
    xor     al, ah
    ret

而且xor ax,di可以代替获得 15B 长版本xor eax, edi,但我会在第一个变体中保留"ax,di",以使其更明显地在做什么。

可能更快一点(根据Peter Cordes的说法,我相信他:)((但更长的机器代码和BMI2指令仅在Intel Haswell+ CPU和AMD Excavator(2015(上支持(变体(最后也使用32b xor(:

; input: rdi = 8x packed byte, output al = xorred value
xorAllRdiBytes:
    rorx    rax, rdi, 32
    xor     eax, edi
    rorx    edi, eax, 16
    xor     eax, edi
    xor     al, ah
    ret

(第一种变体仅使用 80386 指令,因此任何x86_64 CPU 都将运行该指令(

我想fuz的3(2(条指令可能会快一点,所以除非你正在优化代码大小,或者你没有SSE4.1,否则这仍然只是第二种解决方案。

最新更新