假设在某些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编程方面不是很有经验,所以也许你们在指令数量方面有更好的解决方案。 谢谢!
答案 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,否则这仍然只是第二种解决方案。