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

 
 
> Локалные переменные в регистры
Student2
сообщение Oct 27 2009, 03:37
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Rst7
сообщение Oct 27 2009, 06:39
Сообщение #2


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

Группа: Модераторы
Сообщений: 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


Но лучше так делать только при сильной необходимости.


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


Частый гость
**

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



Спасибо - это точно что хотел узнать.

Вопрос - а что будет если использовать #pragma inline=forced перед fooxx(). Мне все таки не хочется вызывать процедуру где можно и не вызывать (каждый CALL может сопровождаться громоздким сегментом сохранения - восстановления регистров).
Go to the top of the page
 
+Quote Post

Сообщений в этой теме


Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


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


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