x86 asm function: 14 byte di codice macchina
Versione uint64_t: 24 byte
x86-64 Convenzione di chiamata SysV ( xin edi), ma lo stesso codice macchina funzionerà anche in modalità 32 bit. (Dove leadecodificherà come lea eax, [edi + eax*2], il che dà risultati identici ).
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 byte
Questo è l' output del compilatore dall'uso dell'eccellente idea di maschera di xnor, una volta al contrario. (E opposta terminologia: il bit basso è il bit 0, che è pari, non dispari.)
unsigned onemask_even(unsigned x) {
unsigned emask = ~0U/3;
unsigned e = (x & emask);
return e*2 + ((x - e) >> 1);
}
Non ho trovato alcun miglioramento rispetto a quello che fa il compilatore. Potrei averlo scritto come mov eax, 0x555.../ and eax, edi, ma è della stessa lunghezza.
La stessa funzione per numeri interi a 64 bit richiede 24 byte (vedere il collegamento godbolt). Non vedo alcun modo inferiore a 10 byte movabs rax, 0x55...per generare la maschera in un registro. (Le divistruzioni di x86 sono goffe, quindi la divisione senza segno di tutti per 3 non aiuta.)
Ho creato un loop per generare la maschera in rax, ma è di 10 byte (esattamente la stessa lunghezza della 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
...
Se sapessimo che nessuno dei byte esistenti raxha il loro bit basso impostato, potremmo saltare il xor, e questo sarebbe lungo 8 byte.
Una versione precedente di questa risposta aveva un loop di 10 byte che utilizzava l' loopinsn, ma aveva un tempo di esecuzione nel caso peggiore di 0xFFFFFFFFFFFFFF08iterazioni, perché avevo impostato solo cl.