Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: поменять местами биты в байте
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Vny4ek
Ребят подскажите плиз как реализовать ума не приложу.
принимаю данные с шины и с первого байта приходящего забиваю в буфер
например буфер байт temp[4]={0x72,0x8C,0x23,0x6B};
потом в ходе выполнения программы оказывается нужно еще эти биты использовать но не слева направа формировать из бит байт а справа на лево
например 0х72=01110010b у меня первый байт принятый, а нужно что бы он стал последним, тоесть взять данные и записать их например в другой массив, но использовать биты не слева направо а справа налево тоесть эти биты 0х72=01110010b которые у меня были первыми на самом деле сформировывать должны последний байт и получается 0х9С. Переписывать процедуру приема можно конечно но мне нужно и так и так. Как проще сделать подскажите пожалуста. Пишу на Си для кодвижен
zltigo
Цитата(Vny4ek @ Apr 25 2010, 21:34) *
0х72=01110010b ... сформировывать должны .... 0х9С.

Не хилое какое-то преобразование, явно не соответствует написанному.
aaarrr
Цитата(zltigo @ Apr 25 2010, 23:45) *
Не хилое какое-то преобразование, явно не соответствует написанному.

Еще сдвиг на один бит появился.
ASN
Vny4ek
тут есть
Vny4ek
я это вижу как цикл на 8 шагов
где проверяется значение последнего бита в байте и это значение присваивается первому биту новому байту ну и затем сдвиг обоих на 1 вот только знаний не хватает как реализовать
да в пересчете я наврал, ну думаю принцип Вы поняли что я пытался объяснить smile.gif
baralgin
Сумбурное описание, но если правильно понял то типа того:
Код
uint8_t InverseByte(uint8_t b)
{
    uint8_t ret = 0;
    for( int i = 0; i < 8; i++ )
    {
        ret |= ( ( b & ( 1 << i )  ) ? 1 : 0 ) << ( 7 - i );
    }
    return ret;
}

0x72->0x4E
KRS
IMHO цикл тут неоптимален.
Можно же стандартный способ использовать примерно так он пишется:
Код
a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1);
a = ((a & 0xCC) >> 2) | ((a & 0x33) << 2);
a = (a >> 4) | (a << 4);
demiurg_spb
Если вопрос звучал так: "Как зеркалить биты в байте?" то самым быстрым способом является таблица из 256 байт (индексом будет исходный байт).
baralgin
Цитата(KRS @ Apr 25 2010, 23:46) *
Можно же стандартный способ использовать примерно так он пишется:
Код
a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1);
a = ((a & 0xCC) >> 2) | ((a & 0x33) << 2);
a = (a >> 4) | (a << 4);

Прикольно, наверное Кнут? smile.gif
Цикл всегда можно развернуть, правда там всё равно на два действия выходит больше...
zltigo
Цитата(baralgin @ Apr 25 2010, 22:57) *
Цикл всегда можно развернуть, правда там всё равно на два действия выходит больше...

То, что Вы написали весьма страшно sad.gif. И дело не в цикле (например стремимся к минимальному размеру, тогда прием KRS отдыхает) а в том, как он написан. Такое:
Код
uint8_t InverseByte(uint8_t b)
{
    uint8_t ret = 0;
    for( uint8_t i = 0x80; i; i >>= 1 )
    {
        if( b & 1 )
             ret |= i;
        b >>= 1;
    }
    return ret;
}

будет в разы короче и быстрее.

А такое, чуть увеличившись в размере, если повезет smile.gif, обгонит KRS и по скорости:
Код
uint8_t InverseByte(uint8_t b)
{
    uint8_t ret = 0;
    for( uint8_t i = 0x80; b; b >>= 1  )
    {
        if( b & 1 )
             ret |= i;
        i >>= 1;
    }
    return ret;
}
baralgin
Не поленился, проверил (плохая привычка меряться.. на ночь глядя smile.gif ).
CODE
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <stdint.h>

static uint8_t InverseByte_zltigo(int b )
{
int ret = 0;
for( int i = 0x80; i; i >>= 1 )
{
if( b & 1 )
ret |= i;
b >>= 1;
}
return ret;
}

static uint8_t InverseByte_zltigo2(int b )
{
int ret = 0;
for( int i = 0x80; b; b >>= 1 )
{
if( b & 1 )
ret |= i;
i >>= 1;
}
return ret;
}

static uint8_t InverseByte(int b )
{
return
(
(b & 0x01) << 7 |
(b & 0x02) << 5 |
(b & 0x04) << 3 |
(b & 0x08) << 1 |
(b & 0x10) >> 1 |
(b & 0x20) >> 3 |
(b & 0x40) >> 5 |
(b & 0x80) >> 7
);
}

static void Benchmark( uint8_t (*test_func)(int))
{
LARGE_INTEGER start, end;
QueryPerformanceCounter(&start);
int seed = 0x72;
for(int i = 0; i < 100000000; i++ )
seed = test_func(seed);
QueryPerformanceCounter(&end);
std::cout << "time=" << end.QuadPart - start.QuadPart << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
Benchmark( &InverseByte_zltigo );
Benchmark( &InverseByte_zltigo2 );
Benchmark( &InverseByte );

return 0;
}

Результат на моём процессоре (A64, Brisbane, L2=512kb):
time=11045076
time=6801262
time=3793456

Видимо сравнения мешают. Я внёс немного самодеятельности и обозвал все внутренние переменные int'ом - так быстрее(для всего что выше avr).

ps: но по скорости всё равно таблица рулит, как предложили выше.
ps2: мой развёрнутый цикл идёт из немного модифицированного первого варианта: ret |= ( ( b & ( 1 << i ) ) >>i ) << ( 7 - i );
ps3: от порядка следования тестов результат конечно же зависит, но кардинально ничего не меняет.
zltigo
Цитата(baralgin @ Apr 25 2010, 23:55) *
Не поленился

Сильно поленились - у Автора всего лишь AVR а не Atlon . А во вторых и для AVR8 это фатально, переврали мои примеры и вписали int вместо insigned char. В третьих, а почему свой вариант не протестировали smile.gif?
Вот как он выглядит на AVR8:
Код
     15          BYTE InverseByte(BYTE b)
   \                     InverseByte:
     16          {
   \   00000000   2F59               MOV     R21, R25
   \   00000002   2F68               MOV     R22, R24
   \   00000004   2F30               MOV     R19, R16
     17              BYTE ret = 0;
   \   00000006   E020               LDI     R18, 0
     18              for( int i = 0; i < 8; i++ )
   \   00000008   E080               LDI     R24, 0
   \   0000000A   E090               LDI     R25, 0
     19              {
     20                  ret |= ( ( b & ( 1 << i )  ) ? 1 : 0 ) << ( 7 - i );
   \                     ??InverseByte_0:
   \   0000000C   2F48               MOV     R20, R24
   \   0000000E   E001               LDI     R16, 1
   \   00000010   E010               LDI     R17, 0
   \   00000012   ....               RCALL   ?S_SHL_L02
   \   00000014   2F13               MOV     R17, R19
   \   00000016   2310               AND     R17, R16
   \   00000018   F011               BREQ    ??InverseByte_1
   \   0000001A   E001               LDI     R16, 1
   \   0000001C   C001               RJMP    ??InverseByte_2
   \                     ??InverseByte_1:
   \   0000001E   E000               LDI     R16, 0
   \                     ??InverseByte_2:
   \   00000020   E010               LDI     R17, 0
   \   00000022   E047               LDI     R20, 7
   \   00000024   1B48               SUB     R20, R24
   \   00000026   ....               RCALL   ?S_SHL_L02
   \   00000028   2B20               OR      R18, R16
     21              }
   \   0000002A   9601               ADIW    R25:R24, 1
   \   0000002C   3088               CPI     R24, 8
   \   0000002E   E000               LDI     R16, 0
   \   00000030   0790               CPC     R25, R16
   \   00000032   F364               BRLT    ??InverseByte_0
     22              return ret;
   \   00000034   2F02               MOV     R16, R18
   \   00000036   2F86               MOV     R24, R22
   \   00000038   2F95               MOV     R25, R21
   \   0000003A   9508               RET
     23          }

А так нормально написанный цикл
Код
     15          BYTE InverseByte(BYTE b)
   \                     InverseByte:
     16          {
     17              BYTE ret = 0;
   \   00000000   E020               LDI     R18, 0
     18              for( BYTE i = 0x80; i; i >>= 1 )
   \   00000002   E810               LDI     R17, 128
     19              {
     20                  if( b & 1 )
   \                     ??InverseByte_0:
   \   00000004   FB00               BST     R16, 0
   \   00000006   F40E               BRTC    ??InverseByte_1
     21                      ret |= i;
   \   00000008   2B21               OR      R18, R17
     22                  b >>= 1;
   \                     ??InverseByte_1:
   \   0000000A   9506               LSR     R16
     23              }
   \   0000000C   9516               LSR     R17
   \   0000000E   F7D1               BRNE    ??InverseByte_0
     24              return( ret );
   \   00000010   2F02               MOV     R16, R18
   \   00000012   9508               RET
     25          }


А в четвертых попробуйте этот Ваш сравнительный тест, например, на 0x01 и узнаете немного о везении.
KRS
Цитата(baralgin @ Apr 26 2010, 01:55) *
ps: но по скорости всё равно таблица рулит, как предложили выше.

Не всегда, все от чипа зависит wink.gif У некоторых есть инстркуция которая порядок битов меняет.
baralgin
Цитата(zltigo @ Apr 26 2010, 01:04) *
Сильно поленились - у Автора всего лишь AVR а не Atlon . А во вторых и для AVR8 это фатально, переврали мои примеры и вписали int вместо insigned char. В третьих, а почему свой вариант не протестировали smile.gif? А в четвертых попробуйте этот сравнительный тест, например, на 0x01 и узнаете немного о везении.

Во первых под рукой нет avr и именно по этому uint8_t превратился в int. Для avr конечно нужно просто uint8_t.
Далее свой(первый) вариант протестировал... и он оказался быстрее всех laughing.gif - смотрел несколько раз, менял местами тесты. Быстрее он. Видимо архитектура процессора+ компилятор(VS2008Express, оптимизация на скорость).
Насчёт 0x01: не корректно. Потому что компилятор умудряется считать результат до исполнения smile.gif . Зато есть более корректный способ: подать в функцию случайную последовательность. Тогда влияние кэша и предсказателя(и возможно других фишек процессора) будет меньше. Вот новый вариант(с первой функцией) и случайным входом:
CODE
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <stdint.h>

static uint32_t x, y, z, w;
static void reset_xor128()
{
x = 123456789;
y = 362436069;
z = 521288629;
w = 88675123;
}

static uint32_t xor128()
{
uint32_t t;
t=(x^(x<<11));x=y;y=z;z=w;
return(w=(w^(w>>19))^(t^(t>>8)));
}

static uint8_t InverseByte_zltigo(int b )
{
int ret = 0;
for( int i = 0x80; i; i >>= 1 )
{
if( b & 1 )
ret |= i;
b >>= 1;
}
return ret;
}

static uint8_t InverseByte_zltigo2(int b )
{
int ret = 0;
for( int i = 0x80; b; b >>= 1 )
{
if( b & 1 )
ret |= i;
i >>= 1;
}
return ret;
}

static uint8_t InverseByte_unroll(int b )
{
return
(
(b & 0x01) << 7 |
(b & 0x02) << 5 |
(b & 0x04) << 3 |
(b & 0x08) << 1 |
(b & 0x10) >> 1 |
(b & 0x20) >> 3 |
(b & 0x40) >> 5 |
(b & 0x80) >> 7
);
}

static uint8_t InverseByte_first(int b )
{
int ret = 0;
for( int i = 0; i < 8; i++ )
{
ret |= ( ( b & ( 1 << i ) ) ? 1 : 0 ) << ( 7 - i );
}
return ret;
}

static void Benchmark( uint8_t (*test_func)(int))
{
LARGE_INTEGER start, end;
reset_xor128();
QueryPerformanceCounter(&start);
for(int i = 0; i < 100000000; i++ )
test_func( xor128() & 0xFF );
QueryPerformanceCounter(&end);
std::cout << "time=" << end.QuadPart - start.QuadPart << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
Benchmark( &InverseByte_unroll );
Benchmark( &InverseByte_first );
Benchmark( &InverseByte_zltigo );
Benchmark( &InverseByte_zltigo2 );

return 0;
}

И результат:
time=4589919
time=4583382
time=18303765
time=16308624

ps: После нескольких испытаний пришёл всёже выводу что InverseByte_unroll и InverseByte_first примерно равны по скорости. Но в любом случае это всё архитектурнозависимо и тестировать нужно на том железе, где будет работать(оказывается что даже инструкции специальные для этого бывают smile.gif ).
Vny4ek
я проще себе это представлял, не знаю только как на языке реализовать:
например
проверяем значение правого бита и присваиваем его левому биту нового байта
далее сдвигаем на 1 в исходном байте вправо (2ой по счету бит справа становится снова 1ым)
также сдвигаем влево на 1 биты в новом байте и повторяем процедуру. так 8 раз
zltigo
Цитата(Vny4ek @ Apr 26 2010, 07:33) *
я проще себе это представлял, не знаю только как на языке реализовать:

Все плохо, Вы, как оказалось, не только написать не можете, но и прочитать уже написанное sad.gif. Ибо все варианты с циклом в таком стиле и делают.
Надо учить язык.


Цитата(baralgin @ Apr 26 2010, 00:31) *
Насчёт 0x01: не корректно. Потому что компилятор умудряется считать результат до исполнения smile.gif .

Вообще-то причина не в этом, а том, что цикл будет прерван как только закончатся единичные биты в старшей части байта.
Цитата
оказывается что даже инструкции специальные для этого бывают smile.gif ).

А когда не бывают, можно сопроцессор smile.gif поставить. Много лет назад, когда по ошибке разработчиков периферийного оборудования (несколько стативов) на CPU на шустром (аж целых 12MHz) 80286 сыпались 32 последовательных потока из развернутых байт, поставил в помощь к процессору 8bit регистр с выходами перекрестно запаралеленными на входы. Записал в него байт и считал развернутым.
KRS
Для AVR все равно быстрее так
Код
uint8_t rsb(uint8_t a)
{
    a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1);
    a = ((a & 0xCC) >> 2) | ((a & 0x33) << 2);
    return __swap_nibbles(a);
}

15 тактов. Даже если на асм написать развернутый цикл со сдвигом через перенос получится 16 тактов.
Код
5              a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1);
   \   00000000   2F10                       MOV     R17,R16
   \   00000002   7515                       ANDI    R17,0x55
   \   00000004   0F11                       LSL     R17
   \   00000006   7A0A                       ANDI    R16,0xAA
   \   00000008   9506                       LSR     R16
   \   0000000A   2B01                       OR      R16,R17
      6              a = ((a & 0xCC) >> 2) | ((a & 0x33) << 2);
      7              return __swap_nibbles(a);
   \   0000000C   2F10                       MOV     R17,R16
   \   0000000E   7C1C                       ANDI    R17,0xCC
   \   00000010   9516                       LSR     R17
   \   00000012   9516                       LSR     R17
   \   00000014   7303                       ANDI    R16,0x33
   \   00000016   0F00                       LSL     R16
   \   00000018   0F00                       LSL     R16
   \   0000001A   2B01                       OR      R16,R17
   \   0000001C   9502                       SWAP    R16
   \   0000001E   9508                       RET
zltigo
Цитата(KRS @ Apr 26 2010, 09:56) *
Для AVR все равно быстрее так

А что, кто-то для общего случая разворота битов, возражал?
Vny4ek
Цитата
Все плохо, Вы, как оказалось, не только написать не можете, но и прочитать уже написанное sad.gif. Ибо все варианты с циклом в таком стиле и делают.
Надо учить язык.

да я с этим полностью согласен, вроде принцип реализации правильно изложил, а на практике написать не могу, если бы на русском ткнули в учебник где можно было понять, как извлечь бит из байта, как установить 0 или 1 в нужном месте байта был бы признателен. Инфы много, но то что читаю либо не содержит такие вещи либо уже идет слишком сложно и не могу просто понять.
smac
Цитата(Vny4ek @ Apr 26 2010, 21:12) *
Инфы много, но то что читаю либо не содержит такие вещи либо уже идет слишком сложно и не могу просто понять.

Да фиг с ними с учебниками, Вы тему-то свою с начала до конца внимательно перечитайте. Как перечитаете выберите один из предложенных вариантов, перечитайте его еще раз, попытайтесь понять, затем задайте вопросы, если что-то останется непонятным.
sigmaN
Vny4ek вот как-то так:
установить бит в байте
Код
b |= 1 << bit_number;

сбросить бит в ноль
Код
b &= ~(1 << bit_number);

bit_number, естественно от 0 до 7, 15 или 31 или даже 63 в зависимости от типа переменных smile.gif
*Для типов подлиннее(длиннее int) придётся указать явное приведение к нужному типу, иначе то, что в скобках - будет приводиться к int(в общем случае).
demiurg_spb
Цитата(KRS @ Apr 26 2010, 11:56) *
Даже если на асм написать развернутый цикл со сдвигом через перенос получится 16 тактов.
Можно и так, но не менее 16 тактов...
Код
BLD R16,0
BST R17,7

BLD R16,1
BST R17,6

BLD R16,2
BST R17,5

BLD R16,3
BST R17,4

BLD R16,4
BST R17,3

BLD R16,5
BST R17,2

BLD R16,6
BST R17,1

BLD R16,7
BST R17,0
А ещё кто-то предлагал соединить два 8-ми битных порта перемычками крест-накрест и инвертировать за 2-3 такта:
Код
out PORTB, R16
nop
in R17,PORTD
x736C
Цитата(KRS @ Apr 26 2010, 11:56) *
Для AVR все равно быстрее так
Код
uint8_t rsb(uint8_t a)
{
    a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1);
    a = ((a & 0xCC) >> 2) | ((a & 0x33) << 2);
    return __swap_nibbles(a);
}

15 тактов. Даже если на асм написать развернутый цикл со сдвигом через перенос получится 16 тактов.
Код
...

С первой половиной согласен — 6 тактов, вторая половина могла бы уложиться в 5 без лишних сдвигов.
Итого 11 тактов против 15.
Код
uint8_t rsb(uint8_t a)
{    a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1);
    return __swap_nibbles(a);
    a = ((a & 0x66) | (a & 0x99));        }

mov  r17,r16
lsr  r17
andi r17,0x55
lsr  r16
andi r16,0xAA
or   r16,r17
mov  r17,r16
swap r17
andi r17,0x66
andi r16,0x99
or   r16,r17
(ret)
Vny4ek
sigmaN, спасибо большое. То что написали после вас вообще не понятно мне т.к. я на Си учусь писать.
sergeeff Jr.
Я по простому сделал (как и сказали, при помощи таблицы):
http://forum.vingrad.ru/index.php?showtopi...t&p=2081873
zltigo
Цитата(Vny4ek @ Apr 27 2010, 07:02) *
sigmaN, спасибо большое. То что написали после вас вообще не понятно мне т.к. я на Си учусь писать.

И уже не первый год http://electronix.ru/forum/index.php?showt...=57082&st=0 все о битах спрашиваете. Ну очень "эффективно" идет процесс sad.gif. Может, наконец-то возьмете в руки букварь? А то просто ничего кроме
сказанного здесь http://electronix.ru/forum/index.php?showt...=55513&st=0 SasaVitebsk по поводу очередного Вашего "вопроса":
Цитата
Блин. Во что лень делает....

сказать уже не могу sad.gif.
MrYuran
Цитата(demiurg_spb @ Apr 27 2010, 00:59) *
А ещё кто-то предлагал соединить два 8-ми битных порта перемычками крест-накрест и инвертировать за 2-3 такта:
Код
out PORTB, R16
nop
in R17,PORTD

Я вот не помню, AVR умеет свопить полубайты?
Тогда можно одним портом обойтись с чуть большим количеством тактов
singlskv
Цитата(x736C @ Apr 27 2010, 05:53) *
С первой половиной согласен — 6 тактов, вторая половина могла бы уложиться в 5 без лишних сдвигов.
Итого 11 тактов против 15.
Код
uint8_t rsb(uint8_t a)
{    a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1);
    return __swap_nibbles(a);
    a = ((a & 0x66) | (a & 0x99));        }

mov  r17,r16
lsr  r17
andi r17,0x55
lsr  r16
andi r16,0xAA
or   r16,r17
mov  r17,r16
swap r17
andi r17,0x66
andi r16,0x99
or   r16,r17
(ret)

у Вас какая-то полная фигня в асм тексте(и в С тоже)
после
lsr r17 и
lsr r16 и неиспользования в дальнейшем флага С
Вы младший бит ужо потеряли

короче, меньше 13 тактов и не надейтесь получить smile.gif
эта я Вам как "крупный специалист по перекладыванию битиков" гарантирую... smile.gif
sergeeff Jr.
Блин крутые специалисты, вы проблему решаете или пиписьками меряетесь? Я указал конкретное решение трабла. Без всяких ассемблеров и всякой пурги (см. проблемы с переносимостью). Взял, скопипастил и пользуешься...
aaarrr
Цитата(sergeeff Jr. @ Apr 28 2010, 02:55) *
Взял, скопипастил и пользуешься...

Ага. Взял эдак, скопипастил, грохнул бездумно 256 байт RAM на AVR, и пользуешься. А что, зато "переносимо".
sergeeff Jr.
Я решаю задачи (взяв AVR с большим количеством памяти, чем нужно будет когда то), а уже потом оптимизирую. Вы видимо в обратном порядке, ну что же, флаг в руки.

А во вторых человек настолько хреново разбирается в том, что вы ему пытаетесь объяснить, что помоему тут разговор не об экономии 256 байтах RAM'a...
aaarrr
Цитата(sergeeff Jr. @ Apr 28 2010, 04:09) *
Я решаю задачи (взяв AVR с большим количеством памяти, чем нужно будет когда то), а уже потом оптимизирую.

С таким подходом к решению AVR'а с достаточным количеством памяти может и не найтись. Сначала надо продумать, потом написать, а затем оптимизировать. В предложенном вами решении первая часть отсутствует совершенно.

Я, кстати, тоже использовал табличку для разворота порядка битов на AVR. Только табличка была расположена во флеш с выравниванием по границе 256, а вся операция сводилась к одной команде lpm.
x736C
Цитата(singlskv @ Apr 28 2010, 00:58) *
у Вас какая-то полная фигня в асм тексте(и в С тоже)
после
lsr r17 и
lsr r16 и неиспользования в дальнейшем флага С
Вы младший бит ужо потеряли

короче, меньше 13 тактов и не надейтесь получить smile.gif
эта я Вам как "крупный специалист по перекладыванию битиков" гарантирую... smile.gif

Вы правы, действительно ошибся.
lsl надо заменить на rol, lsr на ror.
11 тактов и получится. Перепроверьте.
Соответственно код на Си тоже надо подправить.

Поправленный код
Код
mov  r17,r16
rol  r17
andi r17,0x55
ror  r16
andi r16,0xAA
or   r16,r17
mov  r17,r16
swap r17
andi r17,0x66
andi r16,0x99
or   r16,r17
sigmaN
Цитата
А во вторых человек настолько хреново разбирается в том, что вы ему пытаетесь объяснить, что помоему тут разговор не об экономии 256 байтах RAM'a
Вот приучится в тупую делать простые вещи и так и будет по табличке всю жизнь. Не на столько сложная задача.

Понятно, что оптимизация просто ради оптимизации - никому не нужна. Но тут другой разговор идет.
AVR - это всё таки не PC и разбрасываться ресурсами(а в конечном итоге и деньгами) ИМХО не стОит.
И что плохого, если люди вступили в дискуссию и пытаются создать максимально оптимальный код под задачу?
Лично я ничего плохого не вижу в этом. Вон с 13 тактов уже на 11 переползли. Может быть некоторые бы и до конца жизни не знали, что это возможно )))))))

И флаг Вам в руки, когда вы с такой привычкой реализуете что-нибудь на меге 128, а другой разработчик сделает тоже самое на тиньке какой-нибудь вшивой smile.gif
singlskv
Цитата(x736C @ Apr 28 2010, 04:36) *
Перепроверьте.
Нет, все равно ошибка.
Смотрите:
Код
mov  r17,r16; r16 = abcdefgh r17=abcdefgh C=x
rol  r17; r17=bcdefghx C=a
andi r17,0x55; r17=0c0e0g0x
ror  r16; r16=aabcdefg C=h
andi r16,0xAA; r16=a0b0d0f0
or   r16,r17; r16=acbedgfx
mov  r17,r16; r17=acbedgfx
swap r17; r17=dgfxacbe
andi r17,0x66; r17=0gf00cb0
andi r16,0x99; r16=a00ed00x
or   r16,r17; r16=agfedcbx

получили agfedcbx
а нужно hgfedcba
x736C
Да, облажался. Мне показалось, АВР делает циклический сдвиг регистра, ступил.
sergeeff Jr.
Такое впечатление, что все ваши начальники понимают, о чем здесь речь и оценивают вашу работу по количеству использованной памяти в мк, а не по результату (работает / не работает). Тоже самое относится ко времени, которое дается на разработку...

Я например не могу объяснить своему начальнику, что такого прекрасного в экономии 256 бит памяти на начальном этапе разработке. А уж тем более почему я потратил на это половину своего рабочего дня. smile.gif
Цитата(sigmaN @ Apr 28 2010, 06:55) *
Вот приучится в тупую делать простые вещи и так и будет по табличке всю жизнь.

А Вы думаете, что большинство делает иначе?
Цитата(sigmaN @ Apr 28 2010, 06:55) *
Понятно, что оптимизация просто ради оптимизации - никому не нужна. Но тут другой разговор идет.
AVR - это всё таки не PC и разбрасываться ресурсами(а в конечном итоге и деньгами) ИМХО не стОит.
И что плохого, если люди вступили в дискуссию и пытаются создать максимально оптимальный код под задачу?
Лично я ничего плохого не вижу в этом. Вон с 13 тактов уже на 11 переползли. Может быть некоторые бы и до конца жизни не знали, что это возможно )))))))

И флаг Вам в руки, когда вы с такой привычкой реализуете что-нибудь на меге 128, а другой разработчик сделает тоже самое на тиньке какой-нибудь вшивой smile.gif

Ничего плохого в этом нет. Просто я бы это все в отдельную тему выделил. Новичек в этой куче сообщений не найдет простого решения (которое будет работать с любым мк).

Сколько времени у Вас уйдет, чтобы переписать этот код на ассемблере для другого Вам неизвестного ранее мк? А при этом Вы профессионал своего дела, а новичек скорее пойдет в соседний форум и найдет там как раз самое просто решение и использует его. biggrin.gif
zltigo
Цитата(sergeeff Jr. @ Apr 28 2010, 15:56) *
Я например не могу объяснить своему начальнику, что такого прекрасного в экономии 256 бит памяти

256 Байт.
Цитата
А уж тем более почему я потратил на это половину своего рабочего дня. smile.gif

А этот уже страшно sad.gif. На эту задачу на 'C' надо тратить 10 минут, даже если ночью разбудить. Набивать таблицу на 256 байт дольше и ошибиться легче.
При этом на 'C', если чуть чуть думать, это будет достаточно портируемый вариант.
Цитата
Сколько времени у Вас уйдет, чтобы переписать этот код на ассемблере для другого Вам неизвестного ранее мк?

Спокойнее, как выяснилось, писать на ассемблере практически бесполезно.
aaarrr
Цитата(sergeeff Jr. @ Apr 28 2010, 17:56) *
Я например не могу объяснить своему начальнику, что такого прекрасного в экономии 256 бит памяти на начальном этапе разработке. А уж тем более почему я потратил на это половину своего рабочего дня. smile.gif

Не бит, а байт. И что такого прекрасного в копипасте безграмотного решения? Или нельзя хотя бы чуть-чуть подумать (да даже не подумать, а просто посмотреть, что копируете), и добавить к таблице модификатор const?
На месте вашего начальника я бы премию срезал, без шуток. Ибо это пример даже не индусского, а китайского кода.
ASN
sergeeff Jr
Тут речь не оптимизации ради оптимизации.
Проинвертировать биты в байте таблицей не факт, что проще. Причин несколько:
- размер кода;
- время на кодирование (или тупое набивание таблицы);
- количество вызовов функции в общем времени работы программы.
Предложенный алгоритм с xor работает быстро.
Более того, в некоторых случаях он вообще будет работать быстрее, чем таблица (если таблицу хранить во внешней медленной памяти).
Отлаженный и качественный алгоритм с одного МК на другой на ассемблере (свежий пример - с 8051 на ARM9) переноситься за 1 день. И даёт выигрыш в производительности 3-8 раз по сравнению с кодом, написанным на C.
Для устройств, где важен каждый милливатт, это зачастую важно. Если Ваше устройство работает от аккумулятора 10 дней (с "вылизанным" ПО на ассемблере), а у конкурентов только 2 дня (на "copypaste'ном" С), то тендер Вы, очень вероятно, проиграете.
Зато потом будет масса времени объяснить своему начальнику, что такого прекрасного в экономии. maniac.gif
sergeeff Jr.
Байт конечно, очепятался я.

Я не говорил, что я не буду искать более красивого решения (что проигнорирую вариант с XOR), но сделаю я это может через месяц, может через два. Потому что как раз каждый милливатт нужен. smile.gif

А тот, кто создал эту тему вообще скорее всего вникать не будет.

А урезателям бонусов еще раз скажу: когда вас поставят в положение - сделай плату, сделай прошивку, подготовь макет с прогой на компе, летим за тридевять земель к клиенту через неделю, тогда я посмотрю что вы будет в коде вылизывать, а главное когда. smile.gif

А "тупое набивание таблицы" кто-то сделал до меня. smile.gif
sergeeff
Если обратите внимание, в последних книгах по программированию, серьезные авторы предупреждают о вреде преждевременной оптимизации. Сначала получи работоспособную программу (устройство), а затем, при необходимости, займись оптимизацией узких мест.
Очевидно, что у каждого программиста со стажем накоплено оптимизированных функций и модулей на 95 % случаев. Автор топика, судя по задаваемому вопросу, программист молодой. Если он над каждым простым вопросом будет сидеть по две недели, конечное устройство не будет разработано в обозримом будущем никогда.
aaarrr
Цитата(sergeeff Jr. @ Apr 28 2010, 20:49) *
А урезателям бонусов еще раз скажу: когда вас поставят в положение - сделай плату, сделай прошивку, подготовь макет с прогой на компе, летим за тридевять земель к клиенту через неделю, тогда я посмотрю что вы будет в коде вылизывать, а главное когда. smile.gif

Думаете, "урезатели бонусов" не умеют работать быстро и качественно? wink.gif

Цитата(sergeeff @ Apr 28 2010, 21:35) *
Если обратите внимание, в последних книгах по программированию, серьезные авторы предупреждают о вреде преждевременной оптимизации. Сначала получи работоспособную программу (устройство), а затем, при необходимости, займись оптимизацией узких мест.

Да, а применение таблицы "из интернета" - это как раз отличный пример преждевременной оптимизации. С соответствующими побочными эффектами sad.gif
sergeeff
Это все на тему - сделать работоспособное устройство (программу) в отведенные для этого временные рамки или развести дискуссию вроде "А не посоветуюте ли какой язык высокого уровня эффективнее использовать в моей разработке?" Жаркие дебаты будут будоражить пытливые умы не одну неделю, разработка будет стоять в ожидании этого самого оптимального ЯВУ. И самое забавное, что дискуссия ничем и не закончится.
KRS
Цитата(sergeeff Jr. @ Apr 28 2010, 20:49) *
А урезателям бонусов еще раз скажу: когда вас поставят в положение - сделай плату, сделай прошивку, подготовь макет с прогой на компе, летим за тридевять земель к клиенту через неделю, тогда я посмотрю что вы будет в коде вылизывать, а главное когда. smile.gif

Ага и работать не будет - потому что в таблице была ошибка wink.gif
Посмотрите например, исходники CRC, там обычно таблицы генерируются на лету, а потом используются. Если надо разместить во флеше - все равно нужна прграмма которая эту таблицу сгенерирует.
А для такой простой операции как обмен бит - таблица это черезмерная оптимизация.
К тому же, если так обмен происходит за 15 тактов - то по таблице будет за 6 тактов ( mov ZL, r16 mov ZH, 0 subi ZL, LOW(-PTR) sbci ZH, HIGH(-PTR) LD R16, Z)
Vny4ek
Всем большое спасибо за помощь. Сам понимаю что тупо не хватает знаний языка. Сейчас стараюсь это устранить.
to zltigo, я разве сказал что в программировании гуру, просто раздел называется для новичков, а то что появляется желание что либо сделать не коммерческое на МК делаю, появляются моменты где не могу разобраться спрашиваю тут. С той поры когда я задавал вопросы по приведенным ссылкам, я (на мой взгляд) подвинулся вперед. Тогда вообще мало понимал. То что интервалы большие между вопросами, так у каждого есть работа, семья, проблемы, дела. Еще раз повторю что я не сидел все это время за МК к сожалению, просто бывает время выпадает и хочется что нибудь свое попробовать сделать. Как то так.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.