在较少的指令中对64位寄存器中的所有字节进行异或

时间:2018-03-10 17:37:31

标签: assembly bit-manipulation nasm x86-64 micro-optimization

假设在某些x86-64平台上,我们在某个64位寄存器中存储了一些64位值(让它成为 RAX )。在较少的指令调用中,challange是 XOR 初始值的所有字节(存储结果的位置无关紧要)。这是我的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编程方面不是很有经验,所以也许你们在指令数量方面有更好的解决方案。 谢谢!

2 个答案:

答案 0 :(得分:4)

这个怎么样?

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


mask    dq 0101010101010101h, 0

这使用无进位乘法pclmullqlqdq来执行一条指令中的所有xors。最后一条指令提取累积结果并将其存储到al

答案 1 :(得分:3)

这支持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可以改为xor eax, edi以获得15B长版本,但我会在第一个版本中保留“ax,di”以使其更明显地在做什么。

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

; 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,否则这仍然只是第二种解决方案。