Цитата(Perepic @ Dec 18 2006, 21:01)

Или вот еще, тоже шедевр. Блин, чем больше в дизассемблере лажу - тем больше расстраиваюсь!
Код
;p_Mask[0] = RxBuf[0];
00011A 910C LD R16,X
00011C 01FC MOVW R30,R24
[...]
000134 01FC MOVW R30,R24
000136 8303 STD Z+3,R16
Простое копирование двух массивов. Ну почему не задействовать пару свободных регистров указателей, скажем Х и Z? Нет, мы будем каждый раз грузить новые значения указателей в ОДНУ регистровую пару, теряя по 2 машинных цикла на каждой итерции. Вроде ж начало получилось хорошее, а дальше... Не понимаю!
Попробовал ради интереса. Получил другие результаты. Код:
Код
char buf1[16];
char buf2[16];
// --------------------------------------------------------------------------
void main(void)
{
buf1[0] = buf2[0];
buf1[1] = buf2[1];
buf1[2] = buf2[2];
buf1[3] = buf2[4];
}
// --------------------------------------------------------------------------
Результат:
Код
buf1[0] = buf2[0];
.... LDI R30, LOW(buf1)
.... LDI R31, (buf1) >> 8
8900 LDD R16, Z+16
8300 ST Z, R16
buf1[1] = buf2[1];
8901 LDD R16, Z+17
8301 STD Z+1, R16
buf1[2] = buf2[2];
8902 LDD R16, Z+18
8302 STD Z+2, R16
buf1[3] = buf2[3];
8903 LDD R16, Z+19
8303 STD Z+3, R16
Ага, но тут массивы объявлены в одном файле, компилятор их "кластеризовал" и обошелся эффективно одним указателем, благо размеры массивов это позволяют. Усложним компилятору задачу, объявив один из массивов внешним:
Код
char buf1[16];
extern char buf2[16];
Результат:
Код
buf1[0] = buf2[0];
.... LDI R26, LOW(buf1)
.... LDI R27, (buf1) >> 8
.... LDI R30, LOW(buf2)
.... LDI R31, (buf2) >> 8
8100 LD R16, Z
930D ST X+, R16
buf1[1] = buf2[1];
8101 LDD R16, Z+1
930D ST X+, R16
buf1[2] = buf2[2];
8102 LDD R16, Z+2
930C ST X, R16
9712 SBIW R27:R26, 2
buf1[3] = buf2[3];
8103 LDD R16, Z+3
01FD MOVW R31:R30, R27:R26
8303 STD Z+3, R16
Он не так печален, как вашем примере. Может все-таки с оптимизацией что-то не то?
Цитата(Perepic @ Dec 18 2006, 21:01)

То же самое, реализованное в цикле. Еще хуже:
Код
;for(i=0; i<4; i++) p_Mask[i] = RxBuf[i];
000118 019C MOVW R18,R24
00011A 018D MOVW R16,R26
[...]
00012A 954A DEC R20
00012C F7C1 BRNE 0x11E
Лучший код генерит только ICC, но вот полчить его в работающем виде и без ограничений по времени/коду пока сложно...
Код:
Код
char buf1[16];
extern char buf2[16];
// --------------------------------------------------------------------------
void main(void)
{
for(char i = 0; i < sizeof(buf1); i++)
{
buf1[i] = buf2[i];
}
}
// --------------------------------------------------------------------------
Результат:
Код
void main(void)
main:
{
019D MOVW R19:R18, R27:R26
for(char i = 0; i < sizeof(buf1); i++)
.... LDI R26, LOW(buf1)
.... LDI R27, (buf1) >> 8
.... LDI R30, LOW(buf2)
.... LDI R31, (buf2) >> 8
E100 LDI R16, 16
{
buf1[i] = buf2[i];
??main_0:
9111 LD R17, Z+
931D ST X+, R17
}
950A DEC R16
F7E1 BRNE ??main_0
}
01D9 MOVW R27:R26, R19:R18
9508 RET
Что может быть короче?
IAR, как уже неоднократно говорилось и доказывалось, является лучшим компилятором для AVR на сегодняшний день. На втором месте с небольшим отставанием прочно находится AVR-GCC. Никакие ICC по качеству кодогенерации с этими двумя соревноваться не могут.
Код, который вы показали, был характерен для IAR'овских компляторов версий 2.хх - они там упорно делали все подобные обращения в память через Z-pointer, что далеко не всегда хорошо, на что было указано и в версиях 3.хх уже ситуация изменилась к лучшему. Основная же причина сидит не в компиляторах, а в самом AVR, в котором мало (всего два) полноценных аппаратных регистра-указателя (Y и Z, X - неполноценный, у него отсутствует очень важный режим адресации со смещением). Т.е. один из указателей занят под указатель стека данных (еще один, мягко говоря, неудачный момент AVR - обо всех этих "фичах" AVR уже подробно говорилось, если интересно, поищите по форуму), остается один Z-pointer, который компилятор и пытается использовать. В данном случае удалось выйти с честью из положения, т.к. производится просто последовательное копирование. А вот если бы надо было выборочно извлекать байты из массивов, то тут X-pointer уже не порулил бы совсем и код был бы действительно печальным.