Нужен ответ на простенький вопрос.
- Войдите на сайт для отправки комментариев
Чт, 08/06/2017 - 03:20
Как поменять местами байты в двухбайтовом слове. Например 0x52FA, а мне нужно 0xFA52
Как поменять местами байты в двухбайтовом слове. Например 0x52FA, а мне нужно 0xFA52
uint16_t a = 0x52FA; Serial.begin(9600); Serial.print(a, HEX); Serial.print(" "); a = (a & 0xFF) << 8 | (a >> 8); Serial.println(a, HEX);52FA FA52
Можно и поизящнее скорее всего, но я открыт к критике.
Вариант кода не лучше вышеперечисленого, но все же хорошо знать и его.
uint16_t a = 0x52FA; Serial.begin(9600); Serial.print(a, HEX); Serial.print(" "); byte b[2], d; uint16_t &c = (uint16_t &)b; c = a; d = b[0]; b[0] = b[1]; b[1] = d; a = c; Serial.println(a, HEX);Спасибо ответившим)
Вариант кода не лучше вышеперечисленого, но все же хорошо знать и его.
Не подскажите, что делает строчка 6 в коде?
Вот вам еще код. в ОДНУ строчку.
Думаю, что ЕвгенийП меня поймет, просто выглядит красиво, почти как брейнфак! ;)
Для прикола - сразу с проверочной програмкой.
#include <stdlib.h> void setup() { Serial.begin(19200); while (!Serial); Serial.println("Input HEX number:"); } void loop() { byte buf[8]="0000000"; uint32_t a=0; uint32_t b=0; byte i=0; while (Serial.available()) { if (i<7) buf[i++] = Serial.read(); } if (!i) return; buf[i] = 0; a = strtol(buf,NULL,16); b = a; //=========ATTENTION!!! BYTES SWAPPING!!! NO EXTRA MEMORY NEEDED!!!=================== *(byte*)&b ^= *((byte*)&b +1) ^= *(byte*)&b ^= *((byte*)&b +1); //=======END OF BYTES SWAPPING======== Serial.print("I have read number:"); Serial.println(a,16); Serial.print("I have swapped bytes:"); Serial.println(b,16); Serial.println("=========================="); Serial.println("Input HEX number:"); }Ну и на асмо-затычке для полноты коллекции :)
Функция принимает 16-битную переменную, переворачивает в ней байты, и отдаёт обратно.
uint16_t asm_func(uint16_t value ){ asm volatile ( "mov __tmp_reg__, %A0" "\n\t" "mov %A0, %B0" "\n\t" "mov %B0, __tmp_reg__" "\n\t" : "=r" (value) : "0" (value) ); return value; }Ну и на асмо-затычке для полноты коллекции :)
а если совместить? без временного регистра на трех XOR? Asm - операция EOR в АВРке.
uint16_t asm_func(uint16_t value ){ asm volatile ( "eor %A0, %B0" "\n\t" "eor %B0, %A0" "\n\t" "eor %A0, %B0" "\n\t" : "=r" (value) : "0" (value) ); return value; }Ничего не выигрываем, те же три такта, но прикольнее.
---------------------------
Ну и проверочная програмка на все способы:
#include <stdlib.h> uint16_t asm_swap(uint16_t value ){ asm volatile ( "eor %A0, %B0" "\n\t" "eor %B0, %A0" "\n\t" "eor %A0, %B0" "\n\t" : "=r" (value) : "0" (value) ); return value; } void setup() { Serial.begin(19200); while (!Serial); Serial.println("Input HEX number:"); } void loop() { byte buf[8]="0000000"; uint32_t a=0; uint32_t b=0; uint32_t c=0; byte i=0; while (Serial.available()) { if (i<7) buf[i++] = Serial.read(); } if (!i) return; buf[i] = 0; a = strtol(buf,NULL,16); b = a; //=========ATTENTION!!! BYTES SWAPPING!!! NO EXTRA MEMORY NEEDED!!!=================== *(byte*)&b ^= *((byte*)&b +1) ^= *(byte*)&b ^= *((byte*)&b +1); //=======END OF BYTES SWAPPING======== c = asm_swap((uint16_t)b); Serial.print("I have read number:"); Serial.println(a,16); Serial.print("I have swapped bytes:"); Serial.println(b,16); Serial.print("swapped back with asm:"); Serial.println(c,16); Serial.println("=========================="); Serial.println("Input HEX number:"); }На асме оказалось на 10 байт толще, чем мой вариант) (на самом деле нет)
Подозреваю, что данный код будет точно как мой самый первый вариант, но мне лень проверять без сериал ридеров и принтов - слишком много править надо)
Для ТСа - изучай битовые операции - это самое низкоуровневое взаимодействие, следовательно малая ресурсоемкость.
454 байта общий вес
void setup() { uint16_t a = 0x52FA; asm_func(a); } void loop() { } uint16_t asm_func(uint16_t value ) { asm volatile ( "eor %A0, %B0" "\n\t" "eor %B0, %A0" "\n\t" "eor %A0, %B0" "\n\t" : "=r" (value) : "0" (value) ); return value; }444 байта
void setup() { uint16_t a = 0x52FA; a = (a & 0xFF) << 8 | (a >> 8); } void loop() { }Аналогично 444 байта:
void setup() { uint16_t a = 0x52FA; asm ( "mov __tmp_reg__, %A0" "\n\t" "mov %A0, %B0" "\n\t" "mov %B0, __tmp_reg__" "\n\t" : "=r" (a) : "0" (a) ); } void loop() { }bargundabal, это потому, что асм-код в функцию завёрнут. Если голяком вставать то меньше будет)
dimax
Неа, 454 байта.
void setup() { uint16_t a = 0x52FA; asm volatile ( "mov __tmp_reg__, %A0" "\n\t" "mov %A0, %B0" "\n\t" "mov %B0, __tmp_reg__" "\n\t" : "=r" (a) : "0" (a) ); } void loop() { }bargundabal, нужно ещё слово "volatile" убрать. Оно создаёт дополнительный код..
Действительно, теперь ровно как моя одна строчка - 444 байта.
Я просто в асме не шарю, поэтому не попробовал, но если честно - асм, как по мне, явно проиграет четырем битовым операциям в одну строку как по читабельности, так и по времени на выдумывание. Хотя последнее зависит от навыка.
Угу теже 444 байта
void setup() { int A = 0x52FA; byte *p = (byte *)&A ; byte b = *p; *p = p[1]; p[1] = b; }Тоже 444 байта. Надо пробовать без стандартных конструкций, либо как-то иначе, но почему-то мне кажется, что все варианты компилятор в итоге причесывает к одному знаменателю.
void setup() { } void loop() { }bargundabal, Сразу не сообразил,- но такой код совершенно бесполезно сравнивать, -компилятор моментом выкинет вашу строчку просто потому, что результат не используется. К моему фрагменту это тоже относится. Т.е. всё, что вы насчитали - не действительно. Нужно куда-то вывести результат. Причём если вывести неудачно, то компилятор опять же оптимизирует код, и переделает по-своему. Т.е. например если преобразование будет только одноразовое в другую переменную, то компилятор расчитает ещё на этапе компиляции результат и запишет его в другую переменную, а самой строчки преобразования не будет в программе вообще :) Видимо нужно создать программу, где в эту функцию будут передаваться неоднократно! неизвестные байты, например прочитанные из порта. Тогда копилятор будет вынужден целиком задействовать алгоритм.)
Протестировал, если ошибся в чем - пиши
Без инвертирования, тестовый образец
//966 байт flash //9 байт RAM #define dataPin 5 #define clockPin 6 #define dataPin2 7 #define clockPin2 8 #define bitOrder MSBFIRST void setup() { byte a = shiftIn(dataPin, clockPin, bitOrder); byte b = shiftIn(dataPin, clockPin, bitOrder); uint16_t ab = (a << 8) | (b); shiftOut(dataPin2, clockPin2, bitOrder, (ab >> 8)); shiftOut(dataPin2, clockPin2, bitOrder, ab); } void loop() {}Инвертирование моим вариантом
//972 байт flash //9 байт RAM #define dataPin 5 #define clockPin 6 #define dataPin2 7 #define clockPin2 8 #define bitOrder MSBFIRST void setup() { byte a = shiftIn(dataPin, clockPin, bitOrder); byte b = shiftIn(dataPin, clockPin, bitOrder); uint16_t ab = (a << 8) | (b); ab = (ab & 0xFF) << 8 | (ab >> 8); shiftOut(dataPin2, clockPin2, bitOrder, (ab >> 8)); shiftOut(dataPin2, clockPin2, bitOrder, ab); } void loop() {}ASM
//972 байт flash //9 байт RAM #define dataPin 5 #define clockPin 6 #define dataPin2 7 #define clockPin2 8 #define bitOrder MSBFIRST void setup() { byte a = shiftIn(dataPin, clockPin, bitOrder); byte b = shiftIn(dataPin, clockPin, bitOrder); uint16_t ab = (a << 8) | (b); asm ( "mov __tmp_reg__, %A0" "\n\t" "mov %A0, %B0" "\n\t" "mov %B0, __tmp_reg__" "\n\t" : "=r" (ab) : "0" (ab) ); shiftOut(dataPin2, clockPin2, bitOrder, (ab >> 8)); shiftOut(dataPin2, clockPin2, bitOrder, ab); } void loop() {}Третий вариант удивил
//992 байт flash //9 байт RAM #define dataPin 5 #define clockPin 6 #define dataPin2 7 #define clockPin2 8 #define bitOrder MSBFIRST void setup() { byte a = shiftIn(dataPin, clockPin, bitOrder); byte b = shiftIn(dataPin, clockPin, bitOrder); uint16_t ab = (a << 8) | (b); byte *p = (byte *)&ab; byte c = *p; *p = p[1]; p[1] = c; shiftOut(dataPin2, clockPin2, bitOrder, (ab >> 8)); shiftOut(dataPin2, clockPin2, bitOrder, ab); } void loop() {}Вот теперь есть последовательность в результатах
Ну это понятно. В компиляторе встроен анализ на такую ситуацию. А вот по указателям нет такого анализа.
//994 байт flash //9 байт RAM #define dataPin 5 #define clockPin 6 #define dataPin2 7 #define clockPin2 8 #define bitOrder MSBFIRST void setup() { byte a = shiftIn(dataPin, clockPin, bitOrder); byte b = shiftIn(dataPin, clockPin, bitOrder); uint16_t ab = (a << 8) | (b); ab = (ab << 3) | (ab >> 3); shiftOut(dataPin2, clockPin2, bitOrder, (ab >> 8)); shiftOut(dataPin2, clockPin2, bitOrder, ab); } void loop() {}Ну и на асмо-затычке для полноты коллекции :)
а если совместить? без временного регистра на трех XOR? Asm - операция EOR в АВРке.
uint16_t asm_func(uint16_t value ){ asm volatile ( "eor %A0, %B0" "\n\t" "eor %B0, %A0" "\n\t" "eor %A0, %B0" "\n\t" : "=r" (value) : "0" (value) ); return value; }Ничего не выигрываем, те же три такта, но прикольнее.
---------------------------
Ну и проверочная програмка на все способы:
#include <stdlib.h> uint16_t asm_swap(uint16_t value ){ asm volatile ( "eor %A0, %B0" "\n\t" "eor %B0, %A0" "\n\t" "eor %A0, %B0" "\n\t" : "=r" (value) : "0" (value) ); return value; } void setup() { Serial.begin(19200); while (!Serial); Serial.println("Input HEX number:"); } void loop() { byte buf[8]="0000000"; uint32_t a=0; uint32_t b=0; uint32_t c=0; byte i=0; while (Serial.available()) { if (i<7) buf[i++] = Serial.read(); } if (!i) return; buf[i] = 0; a = strtol(buf,NULL,16); b = a; //=========ATTENTION!!! BYTES SWAPPING!!! NO EXTRA MEMORY NEEDED!!!=================== *(byte*)&b ^= *((byte*)&b +1) ^= *(byte*)&b ^= *((byte*)&b +1); //=======END OF BYTES SWAPPING======== c = asm_swap((uint16_t)b); Serial.print("I have read number:"); Serial.println(a,16); Serial.print("I have swapped bytes:"); Serial.println(b,16); Serial.print("swapped back with asm:"); Serial.println(c,16); Serial.println("=========================="); Serial.println("Input HEX number:"); }Красиво! Я тоже благоговею от XOR, но вот такого применения еще не делал
Красиво! Я тоже благоговею от XOR, но вот такого применения еще не делал
Б..га побойтесь! Это олимпиадная задачка по программированию. Причем разогревная.
Я такие больше 30 лет назад решал ради драйва....
Вообще не понял, что это должно быть.
Вообще не понял, что это должно быть.
Компилятор выискивает компинации <<8 и 8>> и компилирует их иначе , чем если это было другое число. Вот я и показал , что бы было если бы не было этого анализа. Это как заточеные под камни бенчмарки в противостоянии Интел и АМД. Так что использование комбинации >>8 выгоднее, так как компилятор "забъет" на сдвиг и тупо перенесет байт.
Ну сдвиг на байт самый распространенный сдвиг, отсюда и низкая потребность в памяти. Я почти уверен, что этот сдвиг в одну команду идет независимо от направления, а сдвиг на 3 - да, внезапность.
Красиво! Я тоже благоговею от XOR, но вот такого применения еще не делал
Б..га побойтесь! Это олимпиадная задачка по программированию. Причем разогревная.
Я такие больше 30 лет назад решал ради драйва....
Знаешь почему на Кавказе водители ездят не по правилам? Они их не учили!
За последние лет 10 за рулём учебных авто я не видел ни одного джигита, не по мужски это!
)))
но решение всё же красивое, это я об эстетике программирования, если такая есть
Точно так же скорее всего компилируется и твой вариант. Я не силен в ссылках, но если перепишешь его под такой же сдвиг - будет интересно увидеть размер кода)