x86 asm işlevi: 14 bayt makine kodu
uint64_t versiyonu: 24 bayt
x86-64 SysV arama kuralı ( x
in edi
), ancak bu aynı makine kodu 32bit modunda da çalışacaktır. ( lea
İrade çözülürken lea eax, [edi + eax*2]
, hangi aynı sonuçları verir ).
0000000000000040 <onemask_even>:
40: 89 f8 mov eax,edi
42: 25 55 55 55 55 and eax,0x55555555
47: 29 c7 sub edi,eax
49: d1 ef shr edi,1
4b: 8d 04 47 lea eax,[rdi+rax*2]
4e: c3 ret
4f: <end>
0x4f - 0x40
= 14 bayt
Bu, xnor'ın mükemmel maske-bir kez fikrini ters yönde kullanmaktan derleyici çıktısıdır . (Ve zıt terminoloji: düşük bit, garip olmayan, bit 0'dır.)
unsigned onemask_even(unsigned x) {
unsigned emask = ~0U/3;
unsigned e = (x & emask);
return e*2 + ((x - e) >> 1);
}
Derleyicinin yaptığı hakkında herhangi bir gelişme bulamadım. mov eax, 0x555...
/ Olarak yazmış olabilirim and eax, edi
, ama bu aynı uzunluk.
64bit tamsayılar için aynı işlev 24 bayt alır (godbolt bağlantısına bakın). movabs rax, 0x55...
Maskeyi bir kayıt defterinde oluşturmak için 10 bayttan daha kısa bir yol görmüyorum . (x86'nın div
talimatı clunky, bu yüzden herkesin 3'e göre imzasız bölümü yardımcı olmuyor.)
Maskeyi rax'ta üretmek için bir döngü oluşturdum, ancak 10 byte (tam olarak aynı uzunluk mov imm64
).
# since 0x55 has its low bit set, shifting it out the top of RAX will set CF
0000000000000000 <swap_bitpairs64>:
0: 31 c0 xor eax,eax ; old garbage in rax could end the loop early
0000000000000002 <swap_bitpairs64.loop>:
2: 48 c1 e0 08 shl rax,0x8
6: b0 55 mov al,0x55 ; set the low byte
8: 73 f8 jnc 2 <swap_bitpairs64.loop> ; loop until CF is set
000000000000000a <swap_bitpairs64.rest_of_function_as_normal>:
# 10 bytes, same as mov rax, 0x5555555555555555
# rax = 0x5555...
a: 48 21 f8 and rax,rdi
...
Var olan baytların hiçbirinin rax
düşük bit kümesine sahip olmadığını bilseydik, bunu atlayabiliriz xor
ve bu 8 bayt uzunluğunda olur.
Bu cevabın önceki bir sürümü loop
insn'i kullanan 10 baytlık bir döngüye sahipti, fakat 0xFFFFFFFFFFFFFF08
sadece belirlediğim için en kötü durumdaki yineleme çalışma süresine sahipti cl
.