Страницы

Поиск по вопросам

среда, 24 октября 2018 г.

Побитовый сдвиг массива

Вообще мне нужно последовательно (побитно) передать и потом принять пакет длиной 48 бит.
Если бы пакет был длиной 32 бита, то решение могло бы быть примерно такое:
unsigned long data=0x12345678;
for(i=0;i<32;i++){ if(data & 0x80000000) setb_MOD; else clrb_MOD; data <<= 1; }
Этот код компилируется очень приятно и компактно. Именно так я бы и сделал на ассемблере:
code<<=1; ac: 88 0f add r24, r24 ae: 99 1f adc r25, r25 b0: aa 1f adc r26, r26 b2: bb 1f adc r27, r27 b4: 80 93 63 00 sts 0x0063, r24 b8: 90 93 64 00 sts 0x0064, r25 bc: a0 93 65 00 sts 0x0065, r26 c0: b0 93 66 00 sts 0x0066, r27
Но т.к. пакет имеет длину 48 бит, приходится обяъвлять его как массив и сдвигать его побайтно в цикле:
unsigned char data[6]={0x12,0x34,0x56,0x78,0xAB,0xCD};
for(i=0;i<48;i++){ if(data[5] & 0x80) setb_MOD; else clrb_MOD; for(j=5;j>0;j--){ data[j]<<=1; if(data[j-1] & 0x80) data[j]+=1; } data[0] <<= 1; }
Результаты компиляции несколько зависят от настроек оптимизатора, видно, что делает он ровно то, что ему и положено: т.е. компилирует он довольно буквально и не использует очевидную для человека коснтрукцию (см. выше). Вот что получается:
for(j=5;j>0;j--){ code[j]<<=1; a8: 82 91 ld r24, -Z aa: 88 0f add r24, r24 ac: 80 83 st Z, r24 if(code[j-1]&0x80) ae: 9e 91 ld r25, -X b0: 97 fd sbrc r25, 7 b2: 13 c0 rjmp .+38 ; 0xda <__vector_2+0x74> clrb_MOD; } else{ setb_MOD; } for(j=5;j>0;j--){ b4: 80 e0 ldi r24, 0x00 ; 0 b6: a3 36 cpi r26, 0x63 ; 99 b8: b8 07 cpc r27, r24 ba: b1 f7 brne .-20 ; 0xa8 <__vector_2+0x42> code[j]<<=1; if(code[j-1]&0x80) code[j]+=1; }
Мне бы очень хотелось избежать использования инлайн вставок кода на ассемблере. Во-первых по-тому, что я не очень владею этой техникой и совершенно не представляю как мне обращаться из ассемблерного кода к переменным, объявленным в C. Хотя, я точно знаю, что все это возмжоно.
Есть ли еще какие-то альтернативы получить оптимальный код?


Ответ

Вы все то же самое могли бы сделать, используя тип uint64_t или unsigned long long
Например,
#include
//...
uint64_t data = 0x123456780123;
for ( i = 0; i < 48; i++ ) { ( data & 0x8000000000 ) ? setb_MOD : clrb_MOD; data <<= 1; }

Комментариев нет:

Отправить комментарий