Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Перевернуть байт (поменять биты местами)


Автор: cardinal 26.1.2010, 21:29
то есть есть строка
Код

#define PortOut P2

А потом везде в программе она используется так
Код

PortOut = 0x80;

То есть присваивается значение 0b10000000, а мне нужно прописать обратный порядок битов, то есть 0b00000001 (так для любого значения).

То есть что-нибудь типа
Код

#define Rotate(PortOut) P2

ищу, чтобы я как и раньше писал
Код

PortOut = 0x80;

а присваивалось значение 0x01...

Подскажите плиз...

Автор: comcon1 26.1.2010, 21:40
чисто на уровне препроцессора не Знаю, но там есть операции в 3-4 действия.
http://www-graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious

Автор: Alexeis 26.1.2010, 21:41
Циклический сдвиг битов типа такого?

Цитата(http://lib.web-malina.com/getbook.php?bid=806&page=7)

    #define BITS 16     /* пусть целое состоит из 16 бит */
    #define ROL(x,skew) x=(x<<(skew))|(x>>(BITS-(skew)))
    #define ROR(x,skew) x=(x>>(skew))|(x<<(BITS-(skew)))

Автор: cardinal 26.1.2010, 22:00
Цитата(Alexeis @  26.1.2010,  19:41 Найти цитируемый пост)
Циклический сдвиг битов типа такого?

Это не изменит порядок битов...

comcon1, спасибо, на я поковырявшись нашел такой прикольный вариант:  smile 
Код

#define REVERSEBITS(b)  (BitReverseTable[b])

static BYTE BitReverseTable[256] =
{
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
};


Добавлено через 3 минуты и 25 секунд
Осталось додумать как это в данном случае (с портом P2) в define добавить... smile 

Автор: 17dufa 27.1.2010, 12:38
cardinal, боюсь что оставить запись в виде Port = 0x80; можно единственным образом - создать класс для порта и перегрузить оператор =, но подозреваю что Ваш компилятор такое не потянет.

Автор: xvr 27.1.2010, 13:18
Если компилятор плюсовый, то можно через метапрограмирование (template'ы). Будет чисто compile-time конструкция

Автор: NewDima 27.1.2010, 17:18
xvr,  smile 

Автор: xvr 27.1.2010, 21:18
Код

template<int Length, int ValueIn>
struct BSwap {
 enum {
  Len1 = Length-1,
  Mask = (1<<Length)-1,
  ValueOut = (((ValueIn&1) << Len1) | ((ValueIn>>Len1) & 1) | BSwap<Length-2,(ValueIn>>1)>::ValueOut) & Mask
 }
};

template<int ValueIn>
struct BSwap<0,ValueIn> {
 enum {
  ValueOut = 0
 }
};

template<int ValueIn>
struct BSwap<1,ValueIn> {
 enum {
  ValueOut = ValueIn&1
 }
};

#define SWAP(len,val) (BSwap<len,val>::ValueOut)

#define SWAP_B(v) SWAP(8,v)
#define SWAP_W(v) SWAP(16,v)
#define SWAP_D(v) SWAP(32,v)


Автор: cardinal 27.1.2010, 21:58
Да, я тоже думаю, что самый простой вариант это прошариться по программе и везде заменить
Код

Port = 0x80;

на
Код

Port = REVERSEBITS(0x80);


То есть ничего элегантного с помощью define пока не получается...

Автор: xvr 27.1.2010, 22:01
Цитата(cardinal @ 27.1.2010,  21:58)
То есть ничего элегантного с помощью define пока не получается...

С define не получится, а с классом с перегруженным оператором operator= получится (это если С++)

Автор: cardinal 27.1.2010, 22:08
А я пока не уверен надо ли это... То есть из-за такой ерунды на данном этапе разработки такую хреновину городить smile 

Автор: NewDima 28.1.2010, 07:26
xvr, это я понял (я про код), но как использовать это в рли lvalue?

Автор: xvr 28.1.2010, 10:41
Цитата(NewDima @ 28.1.2010,  07:26)
xvr, это я понял (я про код), но как использовать это в рли lvalue?

Для этого нужен другой класс (17dufa уже озвучивал)
Код

template<int Addr>
class PortDef {
public:
 char operator=(char v)
  {
    *(char*)Addr=SWAP_B(v);
    return v;
  }
};

PortDef<P2> Port;

Port = 0x80;


Автор: NewDima 28.1.2010, 11:14
xvr, ну с перегрузкой оператора то и так ясно, я подумал, может что другое =)

Автор: serg76 1.2.2010, 14:07
Код

  BYTE i=0x80;
  BYTE b=0;

  asm
  {
    rcr i,1
    rcl b,1
    rcr i,1
    rcl b,1
    rcr i,1
    rcl b,1
    rcr i,1
    rcl b,1

    rcr i,1
    rcl b,1
    rcr i,1
    rcl b,1
    rcr i,1
    rcl b,1
    rcr i,1
    rcl b,1
  }

или в цикл

Автор: cardinal 1.2.2010, 21:12
serg76, если честно не очень понимаю, что делает этот код...

Автор: xvr 1.2.2010, 21:32
Цитата(cardinal @ 1.2.2010,  21:12)
serg76, если честно не очень понимаю, что делает этот код...

Это 'код' разворачивает побитно переменную 'i' в переменную 'b'. Делает он это на ассемблере единственного реально существующего в мире процессора, так что все поголовно должны знать его ассемблер как 'отче наш'  smile (Кажется это PIC, но не поручусь)

С исходным вопросом он конечно не имеет ничего общего, но зато 'ассемблер - это круто!'  smile 

Автор: mes 1.2.2010, 21:51
Цитата(cardinal @  1.2.2010,  20:12 Найти цитируемый пост)
если честно не очень понимаю, что делает этот код.

там скрыто используется флаг. 
Если не ошибаюсь, получается два (круговых) стека,  итерационо с одного справа сбрасывается бит во флаг, и с флага запихивается слева в другой,
(а с другого опять через флаг в первый, но это уже вне задания)
Т.е. после проведения операции оба байта будут содержать "зеркальное представление" другого, хотя для законченности не хватает в конце еще одной инструкции  rcr i,1
 smile

Добавлено через 46 секунд
Цитата(xvr @  1.2.2010,  20:32 Найти цитируемый пост)
но зато 'ассемблер - это круто!'  smile

 smile 

Автор: cardinal 1.2.2010, 23:48
Цитата(mes @  1.2.2010,  19:51 Найти цитируемый пост)
там скрыто используется флаг. 

А тогда ясно. Я просто подумал что чисто командами там муть написана smile

Добавлено через 40 секунд
xvr, заметь что про флаг ты ничего не сказал (и наверно даже не подозревал) smile 

Автор: mes 2.2.2010, 01:16
Цитата(cardinal @  1.2.2010,  22:48 Найти цитируемый пост)
заметь что про флаг ты ничего не сказал (и наверно даже не подозревал) 

сильно сомневаюсь, чтоб xvr не знал о флагах    smile   а не сказал скорей всего ввиду "очевидности" сего факта  smile 
дело в том что в асме фактически все операции взаимодействуют через флаги и логика команд неподготовленных программистов ЯВУ легко поставит в затруднение.
smile

Автор: cardinal 2.2.2010, 01:51
Цитата(mes @  1.2.2010,  23:16 Найти цитируемый пост)
а не сказал скорей всего ввиду "очевидности" сего факта  smile 

Ничего очевидного тут нет.

Да и вообще у меня MSP430 мк, у которого хрен знает какие команды и уж тем более, как там дело обстоит с флагами. То есть пока использование в моем случае под вопросом (руки пока не доходят проверить). Сишными командами думаю все таки решить, есть одна идейка...

Автор: mes 2.2.2010, 02:53
Цитата(cardinal @  2.2.2010,  00:51 Найти цитируемый пост)

Ничего очевидного тут нет.

очевидно тем,  кто имел дело с асмом так же как Си`шникам конструкция i+=5; - с ходу и не понятно чем она ставит в тупик остальных smile


Цитата(cardinal @  2.2.2010,  00:51 Найти цитируемый пост)
Сишными командами думаю все таки решить

ну про перестановку вроде бы Вы нашли решение  (и даже не одно) , а в чем сейчас загвоздка ?
нельзя  ли мини пример ? чтоб понять,  что из чего должно получиться ..

Автор: serg76 2.2.2010, 10:39
Цитата
Да и вообще у меня MSP430 мк, у которого хрен знает какие команды и уж тем более, как там дело обстоит с флагами

да с http://msl.gaw.ru/html.cgi/txt/doc/micros/msp430/asm/start.htm совсем плохо

Цитата
Сишными командами думаю все таки решить

код был написан на СВ6

имхо судя по командам проще биты по условию выставлять

Автор: cardinal 2.2.2010, 20:53
Цитата(mes @  2.2.2010,  00:53 Найти цитируемый пост)
а в чем сейчас загвоздка ?

Нет времени, с железом разбираюсь smile 
Цитата(mes @  2.2.2010,  00:53 Найти цитируемый пост)
нельзя  ли мини пример ? чтоб понять,  что из чего должно получиться .

Я через недельку отвечу, т.к. тогда новое железо будет готово и я перейду к программированию...

Автор: cardinal 12.2.2010, 01:56
Цитата(mes @  2.2.2010,  00:53 Найти цитируемый пост)
нельзя  ли мини пример ? чтоб понять,  что из чего должно получиться ..

Итак пример из жизни. Есть два чипа, которые обмениваются информацией при помощи одного порта (8 бит). Но вот незадача - соединения идут крест на крест если посадить оба чипа одной стороне платы. Есть три решения: развести крест на крест (меняя сторону), посадить элементы на разные стороны платы или просто развернуть порядок битов в софте. Я выбрал третье решение, т.к. крест на крест это несуперское решение (общее правило: избегать перекрещивание для того, чтобы сигналы друг друга не портили), а если сажать чипы на разные стороны, то это геморр при сборке платы.

Автор: mes 12.2.2010, 20:36
Цитата(cardinal @  12.2.2010,  00:56 Найти цитируемый пост)
Есть два чипа, которые обмениваются информацией при помощи одного порта (8 бит).

как я понял у каждого чипа своя копия софта?. тогда делаете макрос типа SEND(value) и для софта каждого чипа определяете его нужным образом.
тoгда не возникнет проблем и в дальнейшем , если вдруг вместо реверсного представления битов придется использовать некое другое (например если вынуждены будете пользовать другую развертку соединения чипов). 

Вместо макроса можно использовать функцию - вынести ее определения в разные файлы и для каждого чипа подключать нужный.

P.S. в любом случае естественно  придется полазить в проге и заменить все старые операции на новый макрос..

Автор: cardinal 13.2.2010, 00:30
Цитата(mes @  12.2.2010,  18:36 Найти цитируемый пост)
как я понял у каждого чипа своя копия софта?

Нет у одного из чипов софт не поменять.
Цитата(mes @  12.2.2010,  18:36 Найти цитируемый пост)
тогда делаете макрос типа SEND(value)

Цитата(mes @  12.2.2010,  18:36 Найти цитируемый пост)
Вместо макроса можно использовать функцию

Я решил функцию сделать...
Цитата(mes @  12.2.2010,  18:36 Найти цитируемый пост)
P.S. в любом случае естественно  придется полазить в проге и заменить все старые операции на новый макрос..

Да, это я как раз с сделал. Все завелось с пол оборота. smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)