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

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


Участник
*

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



Доброго времени суток уважаемые форумчане. На этом форуме давно, но отписываюсь не часто, практически по всем вопросам есть информация, за что всем посетителям и администрации поклон в ноги.
При написании кода всегда обращаю внимание на генерируемый ассемблерный листинг, при этом не заострял внимания на указатели.
Недавно обратил внимание на оч. интересный документ AVR035:Эффетивное программирование на Си для AVR (очень жалею, что давно его не прочел) sad.gif
В нем написан интересный способ уменьшения объема кода в случае использования множетсва глобальных переменных. Там предлагается объявить эти переменные как глобальную структуру и обращаться к каждой переменной
как к элементу структуры, при этом указатель на структуру всегда используется один и тот же, а переменные считываются командой 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, все кардинально меняется!!! blink.gif
Вот исходник
Цитата
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
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
pwl
сообщение Apr 1 2011, 17:07
Сообщение #2





Группа: Новичок
Сообщений: 3
Регистрация: 1-04-11
Пользователь №: 64 064



Цитата(ibiza11 @ Apr 1 2011, 19:12) *
НО только я добавляю в цикл функцию delay, все кардинально меняется!!! blink.gif

Видимо, как и любую другую. Ибо:

What registers are used by the C compiler?
Data types:
char is 8 bits, int is 16 bits, long is 32 bits, long long is 64 bits, float and double are 32 bits (this is the only supported floating point format), pointers are 16 bits (function pointers are word addresses, to allow addressing up to 128K program memory space). There is a -mint8 option (see Options for the C compiler avr-gcc) to make int 8 bits, but that is not supported by avr-libc and violates C standards (int must be at least 16 bits). It may be removed in a future release.
Call-used registers (r18-r27, r30-r31):
May be allocated by gcc for local data. You may use them freely in assembler subroutines. Calling C subroutines can clobber any of them - the caller is responsible for saving and restoring.
Call-saved registers (r2-r17, r28-r29):
May be allocated by gcc for local data. Calling C subroutines leaves them unchanged. Assembler subroutines are responsible for saving and restoring these registers, if changed. r29:r28 (Y pointer) is used as a frame pointer (points to local data on stack) if necessary. The requirement for the callee to save/preserve the contents of these registers even applies in situations where the compiler assigns them for argument passing.
Fixed registers (r0, r1):
Never allocated by gcc for local data, but often used for fixed purposes:

это про gcc, но вроде у них похожие abi.
можно попробовать объявить delay как static или inline. может поможет.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- ibiza11   IAR AVR (Cи). вопрос о указателе на глобальную структуру   Apr 1 2011, 12:12
- - 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, 06:56
|- - =GM=   Цитата(ibiza11 @ Apr 5 2011, 05:56) Не по...   Apr 5 2011, 11:36
- - 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


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

 


RSS Текстовая версия Сейчас: 28th June 2025 - 10:26
Рейтинг@Mail.ru


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