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

 
 
> 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
2 страниц V  < 1 2  
Start new topic
Ответов (15 - 22)
SasaVitebsk
сообщение Apr 5 2011, 13:20
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Код
     20            delay(107);
   \   00000002   E60B               LDI     R16, 107
   \   00000004   E010               LDI     R17, 0
   \   00000006   8308               ST      Y, R16
   \   00000008   8319               STD     Y+1, R17
   \                     ??main_0:
   \   0000000A   8108               LD      R16, Y
   \   0000000C   8119               LDD     R17, Y+1
   \   0000000E   2B01               OR      R16, R17
   \   00000010   F7E1               BRNE    ??main_0
   \   00000012   8108               LD      R16, Y
   \   00000014   8119               LDD     R17, Y+1
   \   00000016   5001               SUBI    R16, 1
   \   00000018   4010               SBCI    R17, 0
   \   0000001A   8308               ST      Y, R16
   \   0000001C   8319               STD     Y+1, R17
     21            t *time=&global;
     22            if(++time->sec==60)
   \   0000001E   ....               LDI     R30, LOW(global)
   \   00000020   ....               LDI     R31, (global) >> 8
   \   00000022   8103               LDD     R16, Z+3
   \   00000024   8114               LDD     R17, Z+4
   \   00000026   5F0F               SUBI    R16, 255
   \   00000028   4F1F               SBCI    R17, 255
   \   0000002A   8303               STD     Z+3, R16
   \   0000002C   8314               STD     Z+4, R17
   \   0000002E   330C               CPI     R16, 60
   \   00000030   E020               LDI     R18, 0
   \   00000032   4010               SBCI    R17, 0
   \   00000034   F429               BRNE    ??main_1
     23            {
     24              time->sec=90;
   \   00000036   E50A               LDI     R16, 90
   \   00000038   8303               STD     Z+3, R16
   \   0000003A   8324               STD     Z+4, R18
     25              time->min=70;
   \   0000003C   E406               LDI     R16, 70
   \   0000003E   8302               STD     Z+2, R16
     26            }
     27          }

От замеса зависит. ))
Go to the top of the page
 
+Quote Post
ibiza11
сообщение Apr 5 2011, 13:38
Сообщение #17


Участник
*

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



SasaVitebsk, странно, у Вас компилятор не вызвал функцию delay(), она у Вас инлайновая? При этом вполне исправно использует Z-регистр. Какой у Вас компилятор?
Go to the top of the page
 
+Quote Post
=GM=
сообщение Apr 5 2011, 13:45
Сообщение #18


Ambidexter
*****

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



Цитата(ibiza11 @ Apr 5 2011, 11:42) *
..поскольку инструкции LDS/STS занимают по два слова

Есть модификация LDS/STS, занимает одно слово. Зависит от того, где в памяти размещены переменные.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ibiza11
сообщение Apr 5 2011, 13:54
Сообщение #19


Участник
*

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



Цитата(=GM= @ Apr 5 2011, 17:45) *
Есть модификация LDS/STS, занимает одно слово. Зависит от того, где в памяти размещены переменные.
что за модификация? не слышал об этом ничего... можно подробнее?
Go to the top of the page
 
+Quote Post
=GM=
сообщение Apr 5 2011, 14:42
Сообщение #20


Ambidexter
*****

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



Документ doc0856i (тыц), с.96. Я не говорил, что иар туповат, я сказал "комиляторЫ иногда туповаты" (или почти всегда, в настоящее время)

Вот CVAVR немного притупил
Цитата(SasaVitebsk @ Apr 5 2011, 12:20) *
Код
delay(107);
       LDI        R16,107
       LDI        R17,0
       ST         Y,R16
       STD        Y+1,R17
main0: LD         R16,Y
       LDD        R17,Y+1
       OR         R16,R17
       BRNE       main0
       LD         R16,Y
       LDD        R17,Y+1
       SUBI       R16,1
       SBCI       R17,0
       ST         Y,R16
       STD        Y+1,R17

WINAVR делает задержку более элегантно
Код
delay(107);
        ldi       r24,0x6B     ; 107
        ldi       r25,0x00     ; 0
        rjmp      L2        ; 0xee <main+0x3c>
L1:     sbiw      r24,0x01     ; ticks--
L2:     sbiw      r24,0x00     ; while(ticks)
        brne      L1        ;


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ibiza11
сообщение Apr 5 2011, 21:07
Сообщение #21


Участник
*

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



Спасибо sm.gif всегда думал, что я знаю этот документ))) оказалось я пропустил важный момент. получается если переменная в памяти находится по адресу от 0х40 до 0хBF и используется регистр от 16 до 31, то используется однословная команда LDS sm.gif это стоит учесть при написании ассемблерных модулейsm.gif
Go to the top of the page
 
+Quote Post
=GM=
сообщение Apr 5 2011, 21:25
Сообщение #22


Ambidexter
*****

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



Если в памяти, то от 0х60


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Apr 6 2011, 05:46
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(ibiza11 @ Apr 5 2011, 17:38) *
SasaVitebsk, странно, у Вас компилятор не вызвал функцию delay(), она у Вас инлайновая? При этом вполне исправно использует Z-регистр. Какой у Вас компилятор?

Прошу прощения. Просто не глянул. Кинул функцию в main.c файл. Вот она и заинклудилась. )) Не прочитал, что это для вас принципиально.
Исправил. Показываю
Код
   \                                 In  segment CODE, align 2, keep-with-next
     13          __C_task void main(void)
   \                     main:
     14          {
     15            delay(107);
   \   00000000   E60B               LDI     R16, 107
   \   00000002   E010               LDI     R17, 0
   \   00000004   ....               RCALL   delay
     16            t *time=&global;
     17            if(++time->sec==60)
   \   00000006   ....               LDI     R30, LOW(global)
   \   00000008   ....               LDI     R31, (global) >> 8
   \   0000000A   8103               LDD     R16, Z+3
   \   0000000C   8114               LDD     R17, Z+4
   \   0000000E   5F0F               SUBI    R16, 255
   \   00000010   4F1F               SBCI    R17, 255
   \   00000012   8303               STD     Z+3, R16
   \   00000014   8314               STD     Z+4, R17
   \   00000016   330C               CPI     R16, 60
   \   00000018   E020               LDI     R18, 0
   \   0000001A   4010               SBCI    R17, 0
   \   0000001C   F429               BRNE    ??main_0
     18            {
     19              time->sec=90;
   \   0000001E   E50A               LDI     R16, 90
   \   00000020   8303               STD     Z+3, R16
   \   00000022   8324               STD     Z+4, R18
     20              time->min=70;
   \   00000024   E406               LDI     R16, 70
   \   00000026   8302               STD     Z+2, R16
     21            }
     22          }
   \                     ??main_0:
   \   00000028   9508               RET

Компилятор 5.11
Задержка
Код
      1          void delay(volatile unsigned int ticks)
   \                     delay:
      2          {
   \   00000000   9722               SBIW    R29:R28, 2
   \   00000002   C004               RJMP    ??delay_0
      3            while(ticks) ticks--;
   \                     ??delay_1:
   \   00000004   8108               LD      R16, Y
   \   00000006   8119               LDD     R17, Y+1
   \   00000008   5001               SUBI    R16, 1
   \   0000000A   4010               SBCI    R17, 0
   \                     ??delay_0:
   \   0000000C   8308               ST      Y, R16
   \   0000000E   8319               STD     Y+1, R17
   \   00000010   8108               LD      R16, Y
   \   00000012   8119               LDD     R17, Y+1
   \   00000014   2B01               OR      R16, R17
   \   00000016   F7B1               BRNE    ??delay_1
      4          }
   \   00000018   9622               ADIW    R29:R28, 2
   \   0000001A   9508               RET
Go to the top of the page
 
+Quote Post

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

 


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


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