|
|
  |
Локалные переменные в регистры |
|
|
|
Oct 27 2009, 03:37
|

Частый гость
 
Группа: Участник
Сообщений: 83
Регистрация: 4-08-09
Из: Болгария / София
Пользователь №: 51 737

|
Не тайна что через использование ключевое слово register можно указать компилятору поставит переменную в регистр. В проекте можно тоже указать компилятору не использовать определенные регистры и потом создать глобальные регистровые переменные. Вопрос идет об локальных переменных в какой то процедуре - если в процедуре много переменных оптимизация часто не принимает во внимание мои инструкции поставит переменные в регистры. Например: Код
register uint8_t var1, var2, var3, var4; // переменные в регистры
var1 = 15; // установка значения var2 = 61; var3 = 45; var4 = 1;
DDRA = var1; PORTC = var2; DDRA = var3; DDRB = var4; После компиляции часто можно увидеть что в листинге находиться что то вроде: Код // DDRA = var1; 0000017A E07F LDI R23, 15 // load R23 with 15 0000017C B97D OUT 0x0D, R23 // out to DDRA вместо ожидаемого: Код // DDRA = var1; 0000017C B97D OUT 0x0D, R21 // out directly var1 to DDRA Как можно обмануть компилятору и поставить локальные переменные воистину в регистры (без использование глобальных переменных в регистров).
Сообщение отредактировал Student2 - Oct 27 2009, 03:38
|
|
|
|
|
Oct 27 2009, 05:34
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата ключевое слово register Не указать, а рекомендовать, компилятор сам решает куда и как ее засунуть если есть возможность ее в регистре разместить он ее и сам разместит. В современных компиляторах абсолютно бесполезная директива осталась только для совместимости со стандартом. Цитата В итоге это одна инструкция больше! Какая риазница ? Код LDI R0, 15; // установка значения LDI R1, 61; LDI R2, 45; LDI R3, 1;
OUT DDRA, R0; OUT PORTC, R1; OUT DDRA, R2; OUT DDRB, R3; или Код LDI R0, 15; OUT DDRA, R0; LDI R0, 61; OUT PORTC, R0; LDI R0, 45; OUT DDRA, R0; LDI R0, 1; OUT DDRB, R0;
|
|
|
|
|
Oct 27 2009, 05:59
|

Частый гость
 
Группа: Участник
Сообщений: 83
Регистрация: 4-08-09
Из: Болгария / София
Пользователь №: 51 737

|
Цитата Какая риазница ? Если установка PORTA DDRA произходить в цикле разница получается доволно большая и заметная. Код LDI R0, 15; // установка значения LDI R1, 61; LDI R2, 45; LDI R3, 1;
.... for (uint16_t ii = 0; ii < 1000; ii++) { OUT DDRA, R0; OUT PORTC, R1; OUT DDRA, R2; OUT DDRB, R3; } намного быстрее (1000 clocks!!!!) чем : Код for (uint16_t ii = 0; ii < 1000; ii++) { LDI R0, 15; OUT DDRA, R0; LDI R0, 61; OUT PORTC, R0; LDI R0, 45; OUT DDRA, R0; LDI R0, 1; OUT DDRB, R0; }
Сообщение отредактировал Student2 - Oct 27 2009, 06:00
|
|
|
|
|
Oct 27 2009, 06:39
|

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

|
Посмотрел внимательнее. Судя по всему, компилятор - IAR. Действительно, иногда у него так бывает, жадность до регистров (т.е. не портить лишнего) пересиливает CSE. Я в таких случаях делаю код вот такого плана: Код static void fooxx_stage2(uint8_t var1, uint8_t var2, uint8_t var3, uint8_t var4);
void fooxx(void) { fooxx_stage2(15,61,45,1); }
static void fooxx_stage2(uint8_t var1, uint8_t var2, uint8_t var3, uint8_t var4) { for(uint16_t ii=0; ii<1000; ii++) { DDRD = var1; PORTC = var2; DDRD = var3; DDRB = var4; } } CODE RSEG CODE:CODE:NOROOT(1) // 7 void fooxx(void) fooxx: // 8 { // 9 fooxx_stage2(15,61,45,1); LDI R19, 1 LDI R18, 45 LDI R17, 61 LDI R16, 15 REQUIRE fooxx_stage2 ; // Fall through to label fooxx_stage2 // 10 } // 11
RSEG CODE:CODE:NOROOT(1) // 12 static void fooxx_stage2(uint8_t var1, uint8_t var2, uint8_t var3, uint8_t var4) fooxx_stage2: // 13 { MOVW R21:R20, R25:R24 // 14 for(uint16_t ii=0; ii<1000; ii++) LDI R24, 232 LDI R25, 3 // 15 { // 16 DDRD = var1; ??fooxx_stage2_0: OUT 0x0A, R16 // 17 PORTC = var2; OUT 0x08, R17 // 18 DDRD = var3; OUT 0x0A, R18 // 19 DDRB = var4; OUT 0x04, R19 // 20 } SBIW R25:R24, 1 BRNE ??fooxx_stage2_0 // 21 } MOVW R25:R24, R21:R20 RET
Но лучше так делать только при сильной необходимости.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Oct 27 2009, 13:41
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Rst7 @ Oct 27 2009, 17:05)  Ничего хорошего. В гцц такие объявления: Код static inline void fooxx_stage2(const uint8_t var1, const uint8_t var2, const uint8_t var3, const uint8_t var4); не вызывают указанных проблем с оверхедом. Как по-иарски, не знаю...
|
|
|
|
|
Nov 9 2009, 20:10
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(Student2 @ Oct 27 2009, 07:37)  Не тайна... Компилятор вообще игнорирует ключевое слово register. Если хорошенько подумаете, то поймете почему.
Причина редактирования: Бездумное цитирование
|
|
|
|
|
Nov 19 2009, 19:44
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(Student2 @ Oct 27 2009, 07:37)  Не тайна что через использование ключевое слово register можно указать компилятору поставит переменную в регистр. В проекте можно тоже указать компилятору не использовать определенные регистры и потом создать глобальные регистровые переменные. Вопрос идет об локальных переменных в какой то процедуре - если в процедуре много переменных оптимизация часто не принимает во внимание мои инструкции поставит переменные в регистры. Например: Код
register uint8_t var1, var2, var3, var4; // переменные в регистры
var1 = 15; // установка значения var2 = 61; var3 = 45; var4 = 1;
DDRA = var1; PORTC = var2; DDRA = var3; DDRB = var4; После компиляции часто можно увидеть что в листинге находиться что то вроде: Код // DDRA = var1; 0000017A E07F LDI R23, 15 // load R23 with 15 0000017C B97D OUT 0x0D, R23 // out to DDRA вместо ожидаемого: Код // DDRA = var1; 0000017C B97D OUT 0x0D, R21 // out directly var1 to DDRA Как можно обмануть компилятору и поставить локальные переменные воистину в регистры (без использование глобальных переменных в регистров). Я думаю, обманывать тут никого не нужно. Если судить по приведенному фрагменту кода, то необходимости отводить регистры под однократно используемые константы абсолютно нет. И компилятор это учел. Если бы эти константы использовались не один раЗ, то компилятор возможно и разместил бы их регистрах, но... Тут все зависит от количества локальных переменных. Если их число велико, то всех их в регистрах не разместишь. Поэтому для подобных операций используются рабочие регистры.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|