реклама на сайте
подробности

 
 
10 страниц V  « < 7 8 9 10 >  
Reply to this topicStart new topic
> Перенос кода из под ИАРа на WinAVR, возникают некоторые вопросы...
sonycman
сообщение Nov 30 2008, 21:52
Сообщение #121


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Но всё же даже у гнуса бывают косяки с указателями.
И всего-то с двумя:
Код
    case    USART_SEND_DATA_EX:
        length    =    4 + 4 + 4 + 20;
        *pb++    =    length + 1;
        *pb++    =    command;
        *pb++    =    temperature.cpu;
        *pb++    =    temperature.gpu;
        *pb++    =    temperature.amb;
        *pb++    =    temperature.hdd;
        *pb++   =   fan_speed[FAN_CPU];
        *pb++   =   fan_speed[FAN_SIDE];
        *pb++   =   fan_speed[FAN_REAR];
        *pb++   =   fan_speed[FAN_FRONT];
        *pb++    =    cpuFan.GetManualStatus();
        *pb++    =    rearFan.GetManualStatus();
        *pb++    =    sideFan.GetManualStatus();
        *pb++    =    frontFan.GetManualStatus();
        *pb++    =    cpuFan.minRPM;
        *pb++    =    cpuFan.maxRPM;
        *pb++    =    cpuFan.minCELSIUS;
        *pb++    =    cpuFan.maxCELSIUS;
        *pb++    =    cpuFan.stopCELSIUS;
        *pb++    =    rearFan.minRPM;
        *pb++    =    rearFan.maxRPM;
        *pb++    =    rearFan.minCELSIUS;
        *pb++    =    rearFan.maxCELSIUS;
        *pb++    =    rearFan.stopCELSIUS;
        *pb++    =    sideFan.minRPM;
        *pb++    =    sideFan.maxRPM;
        *pb++    =    sideFan.minCELSIUS;
        *pb++    =    sideFan.maxCELSIUS;
        *pb++    =    sideFan.stopCELSIUS;
        *pb++    =    frontFan.minRPM;
        *pb++    =    frontFan.maxRPM;
        *pb++    =    frontFan.minCELSIUS;
        *pb++    =    frontFan.maxCELSIUS;
        *pb++    =    frontFan.stopCELSIUS;

код получается сплошняком из LDS/STS, так как адреса переменных (члены классов) статические и гнус таким образом "оптимизирует".
После того, как я перевёл приёмник в локальные переменные (пришлось водрузить буффер на стёк), код немного улучшился:
Код
   case    USART_SEND_DATA_EX:
        length    =    4 + 4 + 4 + 20;
        *pb++    =    length + 1;
    1320:    81 e2           ldi    r24, 0x21; 33
    1322:    8b 83           std    Y+3, r24; 0x03
        *pb++    =    command;
    1324:    0c 83           std    Y+4, r16; 0x04
        *pb++    =    temperature.cpu;
    1326:    80 91 62 01     lds    r24, 0x0162
    132a:    8d 83           std    Y+5, r24; 0x05
        *pb++    =    temperature.gpu;
    132c:    80 91 63 01     lds    r24, 0x0163
    1330:    8e 83           std    Y+6, r24; 0x06
        *pb++    =    temperature.amb;
    1332:    80 91 64 01     lds    r24, 0x0164
    1336:    8f 83           std    Y+7, r24; 0x07
        *pb++    =    temperature.hdd;
    1338:    80 91 65 01     lds    r24, 0x0165
    133c:    88 87           std    Y+8, r24; 0x08
        *pb++   =   fan_speed[FAN_CPU];
    133e:    80 91 9d 01     lds    r24, 0x019D
    1342:    89 87           std    Y+9, r24; 0x09
        *pb++   =   fan_speed[FAN_SIDE];
    1344:    80 91 9e 01     lds    r24, 0x019E
    1348:    8a 87           std    Y+10, r24; 0x0a
        *pb++   =   fan_speed[FAN_REAR];
    134a:    80 91 9f 01     lds    r24, 0x019F
    134e:    8b 87           std    Y+11, r24; 0x0b
        *pb++   =   fan_speed[FAN_FRONT];
    1350:    80 91 a0 01     lds    r24, 0x01A0
    1354:    8c 87           std    Y+12, r24; 0x0c
        *pb++    =    cpuFan.GetManualStatus();
    1356:    8f e0           ldi    r24, 0x0F; 15
    1358:    92 e0           ldi    r25, 0x02; 2
    135a:    83 d8           rcall    .-3834   ; 0x462 <CFanRegulatorBase::GetManualStatus()>
    135c:    8d 87           std    Y+13, r24; 0x0d
        *pb++    =    rearFan.GetManualStatus();
    135e:    8c e1           ldi    r24, 0x1C; 28
    1360:    92 e0           ldi    r25, 0x02; 2
    1362:    7f d8           rcall    .-3842   ; 0x462 <CFanRegulatorBase::GetManualStatus()>
    1364:    8e 87           std    Y+14, r24; 0x0e
        *pb++    =    sideFan.GetManualStatus();
    1366:    89 e2           ldi    r24, 0x29; 41
    1368:    92 e0           ldi    r25, 0x02; 2
    136a:    7b d8           rcall    .-3850   ; 0x462 <CFanRegulatorBase::GetManualStatus()>
    136c:    8f 87           std    Y+15, r24; 0x0f
        *pb++    =    frontFan.GetManualStatus();
    136e:    86 e3           ldi    r24, 0x36; 54
    1370:    92 e0           ldi    r25, 0x02; 2
    1372:    77 d8           rcall    .-3858   ; 0x462 <CFanRegulatorBase::GetManualStatus()>
    1374:    88 8b           std    Y+16, r24; 0x10
        *pb++    =    cpuFan.minRPM;
    1376:    80 91 18 02     lds    r24, 0x0218
    137a:    89 8b           std    Y+17, r24; 0x11
        *pb++    =    cpuFan.maxRPM;
    137c:    80 91 17 02     lds    r24, 0x0217
    1380:    8a 8b           std    Y+18, r24; 0x12
        *pb++    =    cpuFan.minCELSIUS;
    1382:    80 91 1a 02     lds    r24, 0x021A
    1386:    8b 8b           std    Y+19, r24; 0x13
        *pb++    =    cpuFan.maxCELSIUS;
    1388:    80 91 19 02     lds    r24, 0x0219
    138c:    8c 8b           std    Y+20, r24; 0x14
        *pb++    =    cpuFan.stopCELSIUS;
    138e:    80 91 1b 02     lds    r24, 0x021B
    1392:    8d 8b           std    Y+21, r24; 0x15
        *pb++    =    rearFan.minRPM;
    1394:    80 91 25 02     lds    r24, 0x0225
    1398:    8e 8b           std    Y+22, r24; 0x16
        *pb++    =    rearFan.maxRPM;
    139a:    80 91 24 02     lds    r24, 0x0224
    139e:    8f 8b           std    Y+23, r24; 0x17
        *pb++    =    rearFan.minCELSIUS;
    13a0:    80 91 27 02     lds    r24, 0x0227
    13a4:    88 8f           std    Y+24, r24; 0x18
        *pb++    =    rearFan.maxCELSIUS;
    13a6:    80 91 26 02     lds    r24, 0x0226
    13aa:    89 8f           std    Y+25, r24; 0x19
        *pb++    =    rearFan.stopCELSIUS;
    13ac:    80 91 28 02     lds    r24, 0x0228
    13b0:    8a 8f           std    Y+26, r24; 0x1a
        *pb++    =    sideFan.minRPM;
    13b2:    80 91 32 02     lds    r24, 0x0232
    13b6:    8b 8f           std    Y+27, r24; 0x1b
        *pb++    =    sideFan.maxRPM;
    13b8:    80 91 31 02     lds    r24, 0x0231
    13bc:    8c 8f           std    Y+28, r24; 0x1c
        *pb++    =    sideFan.minCELSIUS;
    13be:    80 91 34 02     lds    r24, 0x0234
    13c2:    8d 8f           std    Y+29, r24; 0x1d
        *pb++    =    sideFan.maxCELSIUS;
    13c4:    80 91 33 02     lds    r24, 0x0233
    13c8:    8e 8f           std    Y+30, r24; 0x1e
        *pb++    =    sideFan.stopCELSIUS;
    13ca:    80 91 35 02     lds    r24, 0x0235
    13ce:    8f 8f           std    Y+31, r24; 0x1f
        *pb++    =    frontFan.minRPM;
    13d0:    80 91 3f 02     lds    r24, 0x023F
    13d4:    88 a3           std    Y+32, r24; 0x20
        *pb++    =    frontFan.maxRPM;
    13d6:    80 91 3e 02     lds    r24, 0x023E
    13da:    89 a3           std    Y+33, r24; 0x21
        *pb++    =    frontFan.minCELSIUS;
    13dc:    80 91 41 02     lds    r24, 0x0241
    13e0:    8a a3           std    Y+34, r24; 0x22
        *pb++    =    frontFan.maxCELSIUS;
    13e2:    80 91 40 02     lds    r24, 0x0240
    13e6:    8b a3           std    Y+35, r24; 0x23
        *pb++    =    frontFan.stopCELSIUS;
    13e8:    80 91 42 02     lds    r24, 0x0242
    13ec:    8c a3           std    Y+36, r24; 0x24
    13ee:    10 e2           ldi    r17, 0x20; 32
    13f0:    04 c0           rjmp    .+8      ; 0x13fa <usartSendCommand(unsigned char, void const*)+0x1ea>

но всё равно не хватило сообразительности задействовать второй указатель.

ИАР без проблем юзает здесь два указателя даже со статическим буффером pb... smile.gif
Go to the top of the page
 
+Quote Post
singlskv
сообщение Nov 30 2008, 22:08
Сообщение #122


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(sonycman @ Dec 1 2008, 00:52) *
но всё равно не хватило сообразительности задействовать второй указатель.
ИАР без проблем юзает здесь два указателя даже со статическим буффером pb... smile.gif
http://electronix.ru/forum/index.php?showt...mp;#entry506246

ну сделайте и обращение к структуре не статическим
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 1 2008, 01:21
Сообщение #123


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(aesok @ Nov 30 2008, 23:45) *
-Os -fno-ivopts
....
Вы не умеете его готовить.
Не могли бы вы более развернуто прокомментировать этот эффект? Как видно, отключение одной из оптимизаций привело к существенному улучшению кода. Разве в компиляторе не предусмотрен анализ результатов оптимизации? Т.е. если после какой-либо оптимизации код стал хуже по основоному критерию (-Os), то не выполнять эту оптимизацию на данном участке кода. Просто интересно.


Цитата(sonycman @ Nov 30 2008, 23:21) *
Если заставить разрабов ИАРа довести до ума работу с указателями, то в гнусе не останется больше ничего привлекательного...
Скорее наоборот. Если в avr-gcc появится возможность полноценной работы с указателями на разные адресные пространства, то в ИАРе, учитывая его цену, не останется ничего привлекательного для тех, кто стоит перед выбором.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
sonycman
сообщение Dec 1 2008, 01:51
Сообщение #124


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(singlskv @ Dec 1 2008, 02:08) *
ну сделайте и обращение к структуре не статическим

Как? Если создавать копию структуры на стёке - то это опять лишнее место и время.
А как ещё можно сделать переменные класса динамическими без лишнего гиморроя?

Цитата(Сергей Борщ @ Dec 1 2008, 05:21) *
Скорее наоборот. Если в avr-gcc появится возможность полноценной работы с указателями на разные адресные пространства, то в ИАРе, учитывая его цену, не останется ничего привлекательного для тех, кто стоит перед выбором.

Но ведь GCC и так работает с указателями часто лучше, чем IAR?
Зато посмотрите, как он хромает при работе с битовыми полями... sad.gif
Go to the top of the page
 
+Quote Post
Rst7
сообщение Dec 1 2008, 06:53
Сообщение #125


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
А это как ? Если копировать побайтно...


Ну Вы же должны знать главное правило в программировании. Это я насчет соотношения время/размер:
Код
void copy_xor_fast(unsigned char *    dst, unsigned char *    src1, unsigned char *    src2, unsigned char count)
{
  while(count&3)
  {
    *dst++=*src1++^*src2++;
    count--;
  }
  if (count)
  do
  {
    unsigned char v0,v1,v2,v3;
    v0=*src1++;
    v1=*src1++;
    v2=*src1++;
    v3=*src1++;
    v0^=*src2++;
    v1^=*src2++;
    v2^=*src2++;
    v3^=*src2++;
    *dst++=v0;
    *dst++=v1;
    *dst++=v2;
    *dst++=v3;
  }
  while(count-=4);
}


Время в функции 888 тактов.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 1 2008, 09:34
Сообщение #126


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Rst7 @ Dec 1 2008, 09:53) *
Ну Вы же должны знать главное правило в программировании. Это я насчет соотношения время/размер:
я имел в виду побайтово, те байт за проход цикла, но даже здесь
Цитата
void copy_xor_fast(unsigned char *dst, unsigned char *src1, unsigned char *src2, unsigned char count)
Время в функции 888 тактов.
у gcc 809 тактов.
Go to the top of the page
 
+Quote Post
Rst7
сообщение Dec 1 2008, 09:44
Сообщение #127


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
я имел в виду


А я имею в виду, что скорее всего Ваш пример высосан из пальца, чисто для того, чтобы показать узкое место IAR'а.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
aesok
сообщение Dec 1 2008, 16:37
Сообщение #128


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(Сергей Борщ @ Dec 1 2008, 04:21) *
Не могли бы вы более развернуто прокомментировать этот эффект?


Я не знаю этот проход оптимизации, он заменил тело цикла:
*dst++ = *src1++ ^ *src2++;

на:
;; MEM[base: dst + ivtmp.11] = [bit_xor_expr] MEM[base: src2 + ivtmp.11] ^ MEM[base: src1 + ivtmp.11];
;; ivtmp.11 = ivtmp.11 + 1;

Предположив что выполнять в теле цикла 3 сложения регистров и одно сложение с константой выгоднее, чем 4 сложения с константой.

Вот что говориться про это проход:
Код
/* This pass tries to find the optimal set of induction variables for the loop.
   It optimizes just the basic linear induction variables (although adding
   support for other types should not be too hard).  It includes the
   optimizations commonly known as strength reduction, induction variable
   coalescing and induction variable elimination.  It does it in the
   following steps:

   1) The interesting uses of induction variables are found.  This includes

      -- uses of induction variables in non-linear expressions
      -- addresses of arrays
      -- comparisons of induction variables

   2) Candidates for the induction variables are found.  This includes

      -- old induction variables
      -- the variables defined by expressions derived from the "interesting
     uses" above

   3) The optimal (w.r. to a cost function) set of variables is chosen.  The
      cost function assigns a cost to sets of induction variables and consists
      of three parts:

      -- The use costs.  Each of the interesting uses chooses the best induction
     variable in the set and adds its cost to the sum.  The cost reflects
     the time spent on modifying the induction variables value to be usable
     for the given purpose (adding base and offset for arrays, etc.).
      -- The variable costs.  Each of the variables has a cost assigned that
     reflects the costs associated with incrementing the value of the
     variable.  The original variables are somewhat preferred.
      -- The set cost.  Depending on the size of the set, extra cost may be
     added to reflect register pressure.

      All the costs are defined in a machine-specific way, using the target
      hooks and machine descriptions to determine them.

   4) The trees are transformed to use the new variables, the dead code is
      removed.
  
   All of this is done loop by loop.  Doing it globally is theoretically
   possible, it might give a better performance and it might enable us
   to decide costs more precisely, but getting all the interactions right
   would be complicated.  */


Больше информации о этом проходе, а также о том можно ли его более точно настроить для AVR можно попытаться найти в файле tree-ssa-loop-ivopts.c

Цитата(Сергей Борщ @ Dec 1 2008, 04:21) *
Как видно, отключение одной из оптимизаций привело к существенному улучшению кода. Разве в компиляторе не предусмотрен анализ результатов оптимизации?


Нет. Есть порядка 200 проходов, большая часть из которых являются оптимизирующими, друга часть служебными. Для каждого уровня оптимизации существует свой набор проходов. Каждая платформа может модифицировать эти наборы под себя. Пользователь может дополнительно включать отключать проходы с помощью ключей -f*.

Анализатором выступает разработчик/пользователь.

Анатолий.

Сообщение отредактировал aesok - Dec 1 2008, 16:38
Go to the top of the page
 
+Quote Post
sonycman
сообщение Dec 1 2008, 17:08
Сообщение #129


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Заметил интересную особенность GCC по работе с виртуальными функциями.

Есть базовый класс с одной виртуальной функцией:
Код
class    CFanRegulatorBase    {
...
    virtual void pwmOutputValue(byte value) {};
...
};

и четыре производных класса:
Код
class    CCpuRegulator : public CFanRegulatorBase    {
...
    void pwmOutputValue(byte value);
...
};

То есть каждый класс имеет свою уникальную функцию pwmOutputValue.
Для чего компилятор создаёт в памяти таблицу с адресами для каждой такой функции.

В ИАР для этого отводится 2*5 (четыре функции производных классов плюс одна базового) байт памяти программ.

В GCC - почему-то 6*5 байт памяти данных. Не понятно, почему именно шесть байт в таблице, и не совсем понятно, почему именно в оперативке - 30 байт это не мало...

Пока что получается, что ИАР компилирует код более компактный как по ROM, так и по RAM...
Go to the top of the page
 
+Quote Post
singlskv
сообщение Dec 1 2008, 21:40
Сообщение #130


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Rst7 @ Dec 1 2008, 12:44) *
А я имею в виду, что скорее всего Ваш пример высосан из пальца, чисто для того, чтобы показать узкое место IAR'а.
Неа, он взят из реальной проги, вот кусок:
Код
    if (wrtype & 0x02)     // AND или XOR
    {
      if (wrtype & 0x04)     // XOR , wrtype==6
      {
        do {
          tmp1=*pS++;        // данные для записи
          tmp2=*pD;          // данные из базы
          tmp1 ^= tmp2;
          *pD++=tmp1;        // переносим в базу
          *pB++=tmp1;        // заполняем данные ответа
        } while (--len);
      }
      else                   // AND , wrtype==2
      {
        do {
          tmp1=*pS++;        // данные для записи
          tmp2=*pD;          // данные из базы
          tmp1 &= tmp2;
          *pD++=tmp1;        // переносим в базу
          *pB++=tmp1;        // заполняем данные ответа
        } while (--len);
      }
    }
    else                   // REP или OR
    {
      if (wrtype & 0x04)     // OR  , wrtype==4
      {
        do {
          tmp1=*pS++;        // данные для записи
          tmp2=*pD;          // данные из базы
          tmp1 |= tmp2;
          *pD++=tmp1;        // переносим в базу
          *pB++=tmp1;        // заполняем данные ответа
        } while (--len);
      }
      else                   // REP , wrtype==0
      {
        do {
          tmp1=*pS++;        // данные для записи
          *pD++=tmp1;        // переносим в базу
          *pB++=tmp1;        // заполняем данные ответа
        } while (--len);
      }
    }

И IARу плохеет на таком коде, а gcc делает почти 1 в 1 с асм.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 1 2008, 22:15
Сообщение #131


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(aesok @ Dec 1 2008, 18:37) *
Есть порядка 200 проходов, большая часть из которых являются оптимизирующими, друга часть служебными. Для каждого уровня оптимизации существует свой набор проходов. Каждая платформа может модифицировать эти наборы под себя. Пользователь может дополнительно включать отключать проходы с помощью ключей -f*.
Спасибо, очень познавательно.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ARV
сообщение Dec 2 2008, 06:58
Сообщение #132


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



Цитата(singlskv @ Dec 2 2008, 00:40) *
И IARу плохеет на таком коде, а gcc делает почти 1 в 1 с асм.
если в этом коде внутрь цикла do перенести анализ ваших переменных (может, даже вместо if использовать switch), то он станет и короче, да и оттранслируется лучше. ведь разница в четырех ветках всего лишь в способе изменения tmp1....


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
Rst7
сообщение Dec 2 2008, 07:25
Сообщение #133


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
если в этом коде внутрь цикла do перенести анализ ваших переменных (может, даже вместо if использовать switch), то он станет и короче, да и оттранслируется лучше. ведь разница в четырех ветках всего лишь в способе изменения tmp1....


Ну-ну. Код как раз грамотно написан, вынесены из циклов проверки.

Цитата(aesok @ Dec 1 2008, 18:37) *
Вот что говориться про это проход:
....


Все понятно. Я так и предполагал, что это векторизация, не знал только, что можно отключить.

Цитата
а также о том можно ли его более точно настроить для AVR


Ну так для AVR можно сразу выключить эту оптимизацию, потому как нет нативной поддержки в системе комманд. Это будет самая грамотная настройка smile.gif

Цитата
И IARу плохеет на таком коде, а gcc делает почти 1 в 1 с асм.


Плохеет. Спору нет.

Теперь давайте я попробую проявить телепатические способности wink.gif

Приведенный код - это, видимо, разнообразная печаталка символов на графический дисплей? Если да, то имеет смысл развернуть циклы для ускорения, все-таки это самое узкое место в гуйне. А при развороте проигрыша у IAR'а - ну отсилы несколько процентов. Что на общем фоне повышения производительности - так и не заметно.

А вот другого плана алгоритм - я тут попробовал собрать свою процедуру md5, оптимизированную под AVR... Гнусь сдался по всем параметрам - по размеру кода, по скорости, по требуемому стеку (собственно, взаимосвязь проста - ниасилил разложить все что можно в регистрах, полез в стек и сдался).


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
ARV
сообщение Dec 2 2008, 08:04
Сообщение #134


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



Цитата(Rst7 @ Dec 2 2008, 10:25) *
Ну-ну. Код как раз грамотно написан, вынесены из циклов проверки.

позволю себе не согласиться. я сделал такую: "обертку" показанного участка
Код
#include <avr/io.h>

volatile uint8_t wrtype, tmp1, tmp2, len;
volatile uint8_t *pD, *pB, *pS;

int main(void){
   while(1){
      // здесь приведенный участок кода 1 в 1
   }
}

скомпилировал эту программку для atmega128 с опцией -Os, в итоге получил 638 байт программного кода.

затем я модифицировал код, как говорил:
Код
int main(void){
while(1){
   do{
        tmp1=*pS++;      
        tmp2=*pD;    
        if (wrtype & 0x02)  
            if (wrtype & 0x04)  
                tmp1 ^= tmp2;
            else
                tmp1 &= tmp2;
        else
            if (wrtype & 0x04)  
                tmp1 |= tmp2;
          *pD++=tmp1;      
          *pB++=tmp1;      
     } while(--len);  
}}
как я понимаю, логика сохранилась полностью (надеюсь, я не ошибся).
результат компиляции: 360 байт памяти программ.

Разница существенная, не так ли? а замедление скорости работы, думаю, явно не в 2 раза smile.gif

Сообщение отредактировал ARV - Dec 2 2008, 08:07


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
Rst7
сообщение Dec 2 2008, 08:15
Сообщение #135


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
а замедление скорости работы, думаю, явно не в 2 раза


Больше чем в 2 smile.gif


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post

10 страниц V  « < 7 8 9 10 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 18:50
Рейтинг@Mail.ru


Страница сгенерированна за 0.01547 секунд с 7
ELECTRONIX ©2004-2016