|
IAR AVR (Cи). вопрос о указателе на глобальную структуру, как заставить компилятор использовать рег. Z как постоянный указатель |
|
|
|
Apr 1 2011, 12:12
|

Участник

Группа: Участник
Сообщений: 54
Регистрация: 13-01-09
Пользователь №: 43 304

|
Доброго времени суток уважаемые форумчане. На этом форуме давно, но отписываюсь не часто, практически по всем вопросам есть информация, за что всем посетителям и администрации поклон в ноги. При написании кода всегда обращаю внимание на генерируемый ассемблерный листинг, при этом не заострял внимания на указатели. Недавно обратил внимание на оч. интересный документ AVR035:Эффетивное программирование на Си для AVR (очень жалею, что давно его не прочел) В нем написан интересный способ уменьшения объема кода в случае использования множетсва глобальных переменных. Там предлагается объявить эти переменные как глобальную структуру и обращаться к каждой переменной как к элементу структуры, при этом указатель на структуру всегда используется один и тот же, а переменные считываются командой LDD r16,Z+30 (соответственно командой STD записываются обратно). плюс этой команды - использование считывания/записи со смещением, не изменяя при этом регистр Z. я попробовал повторить пример из этой Application Note, все получилось как надо: Цитата typedef struct { int hour; char min; int sec; }t; t global;
__C_task void main1(void) { t *time=&global; if(++time->sec==60) { time->sec=90; time->min=70; } } а это ассемблерный листинг, который генерируется в итоге: Цитата // 10 { // 11 t *time=&global; LDI R16, LOW(global) LDI R17, (global) >> 8 MOVW R31:R30, R17:R16 // 12 if(++time->sec==60) LDD R16, Z+2 INC R16 STD Z+2, R16 CPI R16, 60 BRNE ??main1_0 // 13 { // 14 time->sec=90; LDI R16, 90 STD Z+2, R16 // 15 time->min=70; LDI R16, 70 STD Z+1, R16 // 16 } // 17 } Обратите внимание, что указатель инициализируется сразу в регистры r30,r31 (Z-регистр) и далее вообще не изменяется, а только используется с командами LDD, STD. НО только я добавляю в цикл функцию delay, все кардинально меняется!!! Вот исходник Цитата typedef struct { int hour; char min; int sec; }t; t global; extern void delay(unsigned int);
__C_task void main1(void) { delay(107); t *time=&global; if(++time->sec==60) { time->sec=90; time->min=70; } } А вот ассемблерный листинг Цитата // 12 delay(107); FUNCALL main1, delay LOCFRAME CSTACK, 0, STACK LOCFRAME RSTACK, 2, STACK ARGFRAME RSTACK, 0, STACK LDI R16, 107 LDI R17, 0 RCALL delay // 13 t *time=&global; LDI R16, LOW(global) LDI R17, (global) >> 8 MOVW R27:R26, R17:R16 // 14 if(++time->sec==60) ADIW R27:R26, 2 LD R16, X SBIW R27:R26, 2 INC R16 ADIW R27:R26, 2 ST X, R16 SBIW R27:R26, 2 CPI R16, 60 BRNE ??main1_0 // 15 { // 16 time->sec=90; LDI R16, 90 ADIW R27:R26, 2 ST X, R16 SBIW R27:R26, 2 // 17 time->min=70; LDI R16, 70 ADIW R27:R26, 1 ST X, R16 SBIW R27:R26, 1 // 18 } // 19 } Обратите внимание, что теперь компилятору нафиг не сдался удобный регистр Z и команды LDD и STD вместе взятые. Вместо них он использует регистр X и каждый раз инкрементирует его на необходимый сдвиг, а считывает и записывает командами LD, ST, что естественно занимает больше времени чем команды LDD и STD. При оптимизации по скорости выполнения вообще заменяет указатель константой и обращается к каждому элементу структуры через команды STS LDS (занимающие в два раза больше программной памяти). Вот код функции delay: Цитата void delay(volatile unsigned int ticks) { while(ticks) ticks--; } volatile добавлен исключительно для того, чтобы компилятор не выбросил задержку из кода при оптимизации. Теперь вопрос: Объясните почему так поступает компилятор с командами LDD и STD, и как ему указать что так делать не нужно? Спасибо за внимание и понимание) p.s. Если разместил тему не в том разделе, прошу модераторов перенести ее туда, где будет актуальнее. уважаемые модераторы, изменил <codebox> на <quote> удобнее читать и есть возможность изменять цвет. в <code> нет возможности менять цвет текста.
Сообщение отредактировал ibiza11 - Apr 1 2011, 16:08
|
|
|
|
|
 |
Ответов
|
Apr 5 2011, 06:56
|

Участник

Группа: Участник
Сообщений: 54
Регистрация: 13-01-09
Пользователь №: 43 304

|
Не понимаю, зачем Вам это, с таким упреком сказали "выложите соответствующий код". Тип переменной не повлияет на обращение с указателем на структуру. Вот не поленился: код с закоментированной функцией delay1
Цитата typedef struct { _int hour; _char min; _int sec; }t; t global; void delay1(unsigned int);//прототип функции, тело функции ниже
__C_task void main1(void) { _t *time=&global; _//delay1(107); _if(++time->sec==60) _{ ___time->sec=90; ___time->min=70; _} } Ассемблерный листинг:
Цитата // 13 t *time=&global; ........LDI R16, LOW(global) ........LDI R17, (global) >> 8 ........MOVW R31:R30, R17:R16 // 14 //delay1(107); // 15 if(++time->sec==60) ........LDD R24, Z+3 ........LDD R25, Z+4 ........ADIW R25:R24, 1 ........STD Z+3, R24 ........STD Z+4, R25 ........CPI R24, 60 ........LDI R16, 0 ........CPC R25, R16 ........BRNE ??main1_0 // 16 { // 17 time->sec=90; ........LDI R16, 90 ........LDI R17, 0 ........STD Z+3, R16 ........STD Z+4, R17 // 18 time->min=70; ........LDI R16, 70 ........STD Z+2, R16 // 19 } // 20 }
Ассемблерный листинг с функцией delay1:
Цитата // 13 t *time=&global; ........LDI R16, LOW(global) ........LDI R17, (global) >> 8 ........MOVW R27:R26, R17:R16 // 14 delay1(107); ........LDI R16, 107 ........LDI R17, 0 ........RCALL delay1 // 15 if(++time->sec==60) ........ADIW R27:R26, 3 ........LD R24, X+ ........LD R25, X ........SBIW R27:R26, 4 ........ADIW R25:R24, 1 ........ADIW R27:R26, 3 ........ST X+, R24 ........ST X, R25 ........SBIW R27:R26, 4 ........CPI R24, 60 ........LDI R16, 0 ........CPC R25, R16 ........BRNE ??main1_0 // 16 { // 17 time->sec=90; ........LDI R16, 90 ........LDI R17, 0 ........ADIW R27:R26, 3 ........ST X+, R16 ........ST X, R17 ........SBIW R27:R26, 4 // 18 time->min=70; ........LDI R16, 70 ........ADIW R27:R26, 2 ........ST X, R16 ........SBIW R27:R26, 2 // 19 } // 20 } как видите, симптомы те же)
Сообщение отредактировал ibiza11 - Apr 5 2011, 07:18
|
|
|
|
|
Apr 5 2011, 11:36
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(ibiza11 @ Apr 5 2011, 05:56)  Не понимаю, зачем Вам это, с таким упреком сказали "выложите соответствующий код" Да ну, какие упрёки. Если бы вы не сказали "возможно, что я дизассемблер простого варианта скопипастил, а код уже нового варианта", а просто проверили бы коды на соответствие и сообщили бы, то и моего поста не было бы. А так, я уж было подумал, что компилятор иар не совсем адекватный, решил посмотреть, что там унутре... Тем не менее, нет худа без добра. После оптимизации на данном фрагменте winavr дал 7 слов кода, а iar - 12 слов, несмотря на использование z-регистра. Конечно, это может ничего не значить, может быть в другом месте iar вырвется вперёд, но может и стоит задуматься. Тут соглашусь с СашейВитебским, не надо выкручивать руки си-компилятору и добиваться от него сиюминутной оптимизации, которая однако может сделать вашу программу зависимой не только от компилятора, но даже от его версии. Для себя я решил так, критичные куски выделяю в ассемблерную подпрограмму, остальное на си. Даже представить себе не можете, как упростилась жизнь эмбеддера :-) А раньше я пыхтел, вставляя инлайновые куски, кто только их придумал.. Ещё подумал, как горю помочь. Попробуйте переставить операторы _t *time=&global; _delay1(107); вот так _delay1(107); _t *time=&global; Компиляторы время от времени бывают туповаты, глядишь и сработает.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
Сообщений в этой теме
ibiza11 IAR AVR (Cи). вопрос о указателе на глобальную структуру Apr 1 2011, 12:12 pwl Цитата(ibiza11 @ Apr 1 2011, 19:12) НО то... Apr 1 2011, 17:07 ibiza11 Спасибо за ответ! единственный из всех, кто п... Apr 1 2011, 20:04 pwl Цитата(ibiza11 @ Apr 2 2011, 03:04) Да и ... Apr 2 2011, 00:19 ibiza11 Так ведь указатель инициализируется только после ф... Apr 2 2011, 06:33 pwl Цитата(ibiza11 @ Apr 2 2011, 13:33) Так в... Apr 2 2011, 17:49 ibiza11 не знаю как бороться с этим, придется пока смирить... Apr 4 2011, 05:49 SasaVitebsk Во-первых необязательно глобальные переменные объе... Apr 4 2011, 09:10 ibiza11 Спасибо за ответ.
Отвечать буду тоже по пунктам (е... Apr 4 2011, 12:43 =GM= 2ibiza11
Как-то некрасиво себя IAR ведёт. В структ... Apr 4 2011, 13:56 ibiza11 to =GM=, спасибо) возможно, что я пробовал менят... Apr 4 2011, 16:04 =GM= Ну так, приведите соответствующий код. Оптимизация... Apr 4 2011, 22:19 ibiza11 Простите за недопонимание Не хотел обидеть
Я тоже... Apr 5 2011, 12:42 =GM= Цитата(ibiza11 @ Apr 5 2011, 11:42) ..пос... Apr 5 2011, 13:45  ibiza11 Цитата(=GM= @ Apr 5 2011, 17:45) Есть мод... Apr 5 2011, 13:54   =GM= Документ doc0856i (тыц), с.96. Я не говорил, что и... Apr 5 2011, 14:42 SasaVitebsk Код 20 delay(107);
\ 0000000... Apr 5 2011, 13:20 ibiza11 SasaVitebsk, странно, у Вас компилятор не вызвал ф... Apr 5 2011, 13:38 SasaVitebsk Цитата(ibiza11 @ Apr 5 2011, 17:38) SasaV... Apr 6 2011, 05:46 ibiza11 Спасибо всегда думал, что я знаю этот документ)))... Apr 5 2011, 21:07 =GM= Если в памяти, то от 0х60 Apr 5 2011, 21:25
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|