2015-07-03 48 views
5

Ho quasi implementato l'algoritmo DES con linguaggio C e voglio ottimizzare il mio codice. Quindi ho usato gprof. Ecco parte della relazione:Stringa a 48 bit di otto unità a 6 bit: come ottenere rapidamente 4 bit di ogni unità

Each sample counts as 0.01 seconds. 
    % cumulative self    self  total   
time seconds seconds calls us/call us/call name  
51.78  9.32  9.32 8000000  1.17  1.17 sboxes 
34.71  15.57  6.25 8000000  0.78  0.78 extendRight 
    9.90  17.35  1.78 500000  3.56 35.96 operation 
    2.39  17.78  0.43 8000000  0.05  0.05 xorRightAndKey 

gprof mostra che sboxes funzione occupato 51.78% del tempo.

In sboxes(uchar aucData[6], ...), mi sono stati dati 48 bit, divisi in 8 slot, ciascuno slot di 6 bit.

per ogni slot:

  1. combinano primo bit con ultimo bit per ottenere X;

  2. ottenere 4 bit centrale per ottenere Y;

  3. fare qualcosa con (X, Y);

Ad esempio, 011110 è una scanalatura, così X = 00 e Y = 1111.

Per implementare questo, ho scritto macro per ottenere/bit SET in memoria, qui è il codice relativo:

#define LOCATE(ptr, index) (((char *)(ptr))[(index) >> 3]) 

#define GET_BIT(ptr, index) (LOCATE((ptr), (index)) & (((uchar)0x80) >> ((index) % 8))) 

E qui è il codice per ottenere (X, Y)

uchar basePos = 0x00; 
for (int i = 0; i < 8; ++i) { 
    x = 0; 
    y = 0; 
    basePos = i * 6; // to locate the slot 
    // combine first bit with last bit 
    if (0 != GET_BIT(aucData, basePos)) { 
     x |= 0x02; 
    } 
    if (0 != GET_BIT(aucData, basePos + 5)) { 
     x |= 0x01; 
    } 
    // get continuous 4 bits 
    for (int j = 1; j <= 4; ++j) { 
     if (0 != GET_BIT(aucData, basePos + j)) { 
      y |= (0x01 << (4 - j)); 
     } 
    } 
    // do something with (x, y) 
} 

Quindi la mia domanda è , Mi hanno dato 48 bit, come ottenere i 4 bit centrali il più velocemente possibile?

+3

Se ognuno è di 6 bit, è possibile creare una tabella di ricerca? – Robinson

+0

Scegli uno: C o C++. – fuz

+1

È possibile scrivere routine ottimizzate separatamente per una sequenza che si estende su più byte e per una sequenza che non lo fa. Ciò eviterebbe l'attuale approccio bit-by-bit. – usr2564301

risposta

4

Senza tabella di ricerca:

typedef unsigned long long u64; 

void sboxes(uchar aucData[6]) 
{ 
    u64 v = aucData[0] + (((u64)aucData[1]) << 8) 
    + (((u64)aucData[2]) << 16) 
    + (((u64)aucData[3]) << 24) 
    + (((u64)aucData[4]) << 32) 
    + (((u64)aucData[5]) << 40); 

    for(int i = 0; i < 8; i++) 
    { 
     uchar x = ((v & 1) << 1) | ((v >> 5) & 1); 
     uchar y = ((v >> 1) & 0xF); 
     // do something with x, y 
     printf("x: %hhu, y: %hhu\n", x, y); 

     v >>= 6; 
    } 
} 

diniego completa: non l'ho fatto riferimento. Ma dovrebbe essere veloce. Potresti essere in grado di eseguire il packing in u64 più velocemente, se è ancora troppo lento.

+0

Prima il tuo codice non funziona, ho provato a ripararlo, ma invano. Ad esempio, mi hanno dato 16 bit '00001111 00001111', devo considerare l'ordine dei byte. –

+0

Come funziona? L'ho provato prima di inviarlo. A meno che non abbia frainteso la domanda. Se uno slot ha bit ABCDEF, allora X = FA, Y = BCDE, corretto? A meno che non si stia dicendo che il contenuto dell'array di input non è in ordine (ad es.l'ordine corretto è _not_ aucData [0] -> aucData [1] -> aucData [2] -> ...) – tohoho

+0

X = AF, scusa per la mia capacità di espressione. Se ci viene dato 'uchar aucData [6] = {0xfc, 0x11, 0x22, 0x33, 0x44, 0x55}', allora 'v' sarebbe' 0x000055443322113fc', dopo 'v >> = 6', i 6 bit di destra '0xfc' è scomparso, ma i 6 bit di sinistra di' 0xfc' sono il primo slot. –