以更少的指令对 64 位寄存器中的所有字节进行 XOR
XOR all bytes in 64 bit register in fewer instructions
假设在一些 x86-64 平台上我们有一些 64 位值存储在一些 64 位寄存器中(让它成为 RAX)。挑战是 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编程方面不是很有经验,所以也许你们在指令量方面有更好的解决方案。
谢谢!
这个怎么样?
movq xmm0,rax
pclmullqlqdq xmm0,[mask]
pextrb eax,xmm0,7
mask dq 0101010101010101h, 0
这使用 carry-less 乘法 pclmullqlqdq
在一条指令中执行所有异或运算。最后一条指令提取累加结果存入al
.
这是支持 System V x86_64 ABI(即可直接从 C/C++ 在 64b linux 等中调用),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+ CPUs 和 AMD Excavator (2015) 支持更长的机器代码和 BMI2 指令)变体(最后也使用 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,否则这仍然只是第二种解决方案。
假设在一些 x86-64 平台上我们有一些 64 位值存储在一些 64 位寄存器中(让它成为 RAX)。挑战是 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编程方面不是很有经验,所以也许你们在指令量方面有更好的解决方案。 谢谢!
这个怎么样?
movq xmm0,rax
pclmullqlqdq xmm0,[mask]
pextrb eax,xmm0,7
mask dq 0101010101010101h, 0
这使用 carry-less 乘法 pclmullqlqdq
在一条指令中执行所有异或运算。最后一条指令提取累加结果存入al
.
这是支持 System V x86_64 ABI(即可直接从 C/C++ 在 64b linux 等中调用),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+ CPUs 和 AMD Excavator (2015) 支持更长的机器代码和 BMI2 指令)变体(最后也使用 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,否则这仍然只是第二种解决方案。