Перейти к содержанию
    

Переопределение переменной в теле функции.

23 минуты назад, jenya7 сказал:

расположу в стеке?

Ваши локальные массивы уже в стеке. Где хранятся значения-инициализаторы, которыми вы заполняете локальные массивы в стеке? Откуда они берутся?

Чтобы что-то в стеке расположить, нужно сначала это что-то туда положить. Вопрос: откуда? Где взять это что-то? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 minutes ago, Darth Vader said:

Ваши локальные массивы уже в стеке. Где хранятся значения-инициализаторы, которыми вы заполняете локальные массивы в стеке? Откуда они берутся?

Чтобы что-то в стеке расположить, нужно сначала это что-то туда положить. Вопрос: откуда? Где взять это что-то? 

то есть все инициализируемые локальные переменные хранят свои значения во флеш?

void Foo (void)
{
    int a = 4;
} 

4 сохраниться во флеш?
 

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

26 минут назад, jenya7 сказал:

расположу в стеке?

- Ты где деньги берешь??

- В тумбочке!

- Туда кто кладет?

- Я кладу.

- А где ты их берешь?

:dash2:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 minutes ago, jenya7 said:

на стеке, нет? это как бы его предназначение.

А кто мешает локальные переменные разестить в РОН (регистры общего назначения)? Ваш вопрос слишком общий и размытый. Да, классически аргументы в функцию передаются через стэк. Локальные переменные выделяются на стэке. Но в реальной жизни всё по другому.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 минут назад, jenya7 сказал:

то есть все инициализируемые локальные переменные хранят свои значения во флеш?

Если точнее, то: значения для инициализации локальных переменных хранятся во флеш.

Да, число 4 будет лежать где-то во флеш памяти по какому-то адресу. Когда произойдет вход в функцию Foo(), будет выполнено копирование числа 4 из его адреса размещения во флеш-памяти в локальную переменную а, для которой будет зарезервировано место в стеке. 

Точно так же и с вашими локальными массивами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 minutes ago, jenya7 said:

4 сохраниться во флеш?

Да. Неужели вы сами на этот вопрос ответить не можете: откуда во время выполнения программы процессор возьмёт число 4?

@jenya7, вы же не начинающий разработчик. Если у вас пробелы в таких базовых вопросах, вам следует немного почитать литературку. А может быть вы что-то другое хотите узнать? Вы нам озучьте задачу...

 

Посмотрите в том же мануале на IAR как вообще происходит запуск микроконтроллера до входа в функцию main(). Там есть описание, что происходит. Как инициализируются глобальные переменные, например. А если им не заданы значения, то как они, согласно стандарту, инициализируются нулём.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вот тут я инициализирую переменную костантой

//  125      sys_params.script_ena = 5;
        LDR.N    R5,??DataTable14_17
        MOVS     R0,#+5
        STRB     R0,[R5, #+1]

константа находится в ассемблерной директиве, не? она не копируется из флеш.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 минут назад, jenya7 сказал:

константа находится в ассемблерной директиве, не? она не копируется из флеш.

Даже если и так, то эта ассемблерная директива сама где хранится? Уж не во флеше ли?

Компилятор по своему усмотрению выбирает способ хранения инициализаторов. Зависит от их типа, размера, значения, количества и прочих факторов. В ряде простых случаев, компилятор может "встроить" константу в код ассемблерной инструкции. Но в большинстве случаев нет. Ему придется явным образом копировать значения из флеш-памяти в стек.

Но общее у этих случаев то, что  значения инициализаторов хранятся во флеше. Отдельно или встроенные в код - но во флеше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 minutes ago, Darth Vader said:

Даже если и так, то эта ассемблерная директива сама где хранится? Уж не во флеше ли?

Компилятор по своему усмотрению выбирает способ хранения инициализаторов. Зависит от их типа, размера, значения, количества и прочих факторов. В ряде простых случаев, компилятор может "встроить" константу в код ассемблерной инструкции. Но в большинстве случаев нет. Ему придется явным образом копировать значения из флеш-памяти в стек.

Но общее у этих случаев то, что  значения инициализаторов хранятся во флеше. Отдельно или встроенные в код - но во флеше.

ну понятно что всё находиться во флеш а не появляеться из воздуха, но если константу можно заинлайнить то это лучше, как мне кажется.

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что, jenya7 сказал:

ну понятно что всё находиться во флеш а не появляеться из воздуха, но если константу можно заинлайнить то это лучше, как мне кажется.

Сделайте static или глобальной константой и он её напрямую с флеш прочитает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 минуты назад, jenya7 сказал:

если константу можно заинлайнить то это лучше, как мне кажется.

В простых случаях можно. Когда константа простая и маленькая. А если большая и сложная (массивы, структуры, дабл, лонг-лонг и т.п.) то есть общий универсальный случай, работающий всегда и везде - копирование значений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

37 минут назад, jenya7 сказал:

это лучше, как мне кажется.

Лучший способ - когда константа используется непосредственно из флеш-памяти, где она и хранится. Без промежуточного копирования в локальные переменные в стеке.

Для этого перепишите ваш пример так:

Цитата

 


void Foo (void)
{
    static const int a = 4;
}

Теперь константа а будет использоваться непосредственно из флеш-памяти.

Естественно, это будет работать лишь если а должна быть именно константой по логике работы функции Foo(). Но для вашей функции инициализации дисплея это так и есть. Там все массивы используются, как массивы констант. Вам остается лишь сообщить об этом компилятору.

Изменено пользователем Darth Vader

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 часа назад, jenya7 сказал:

Впервые встретил вот такое


void ILI9341_Init() 
{
    ILI9341_WriteCommand(0xCB);
    {
        uint8_t data[] = { 0x39, 0x2C, 0x00, 0x34, 0x02 };
        ILI9341_WriteData(data, sizeof(data));
    }
  
    ILI9341_WriteCommand(0xCF);
    {
       uint8_t data[] = { 0x00, 0xC1, 0x30 };
       ILI9341_WriteData(data, sizeof(data));
    }
  
    //и так далее
  
  }

стоит пользоваться такой конструкцией? мне она не нравиться честно говоря.

интересно как компайлер поведет себя? выделит отдельный массив на стаке при каждом определении?

имхо, это прекрасный код. лучше не сделать., если разве в макрос убрать объявление этих скобок - в макросе оно красивее выгляделоб

переменным data не хватает const или static const, может быть. Но может это потому что WriteData умеет только из RAM читать.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, jenya7 said:

она не копируется из флеш.

Опять двадцать пять)

43 minutes ago, AlexRayne said:

Но может это потому что WriteData умеет только из RAM читать.

Это как? У армов же линейное пространство памяти. Неважно, откуда читать: из ОЗУ или ЭСПЗУ. На LPC4337 можно даже из EEPROM читать. И нет никакой разницы, кроме быстродействия. Но это к чтению не относится.

1 hour ago, jenya7 said:

но если константу можно заинлайнить то это лучше, как мне кажется.

Вы об чём? Как можно заинлайнить константу? Инлайнят функции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, AlexRayne сказал:

Но может это потому что WriteData умеет только из RAM читать.

Опять 25.... Объясните пожалуйста - каким образом вызывающая функция умеет не только из RAM читать, а вызываемая - не умеет? Это как это???  :wacko2:

6 часов назад, jenya7 сказал:

что то я не очень понимаю


//  178     ILI9341_WriteCommand(0xCB);
        MOVS     R0,#+203
        BL       ILI9341_WriteCommand
//  179     {
//  180         uint8_t data[] = { 0x39, 0x2C, 0x00, 0x34, 0x02 };
        ADD      R0,SP,#+32
        LDR.W    R1,??DataTable15_3
        LDRD     R2,R3,[R1, #+0]
        STRD     R2,R3,[R0, #+0]
//  181         ILI9341_WriteData(data, sizeof(data));
        MOVS     R1,#+5
        ADD      R0,SP,#+32
        BL       ILI9341_WriteData
//  182     }
          
          
//  193     ILI9341_WriteCommand(0xCF);
        MOVS     R0,#+207
        BL       ILI9341_WriteCommand
//  194     {
//  195         uint8_t data[] = { 0x00, 0xC1, 0x30 };
        ADD      R0,SP,#+28
        LDR.W    R1,??DataTable15_4
        LDR      R2,[R1, #+0]
        STR      R2,[R0, #+0]
//  196         ILI9341_WriteData(data, sizeof(data));
        MOVS     R1,#+3
        ADD      R0,SP,#+28
        BL       ILI9341_WriteData
//  197     }

это та же область или разная

судя по офсету на стеке разная.

В данном конкретном случае компиляции - разная. И как раз из данного листинга видно, что более умный оптимизатор запросто может перенести инициализацию обоих data в начало функции, сделать это одновременно (так как это оптимальнее и по размеру и по скорости). А значит (так как оптимизаторы развиваются), то утверждение, что инициализация каждого data выполняется непосредственно перед его использованием - на другом компиляторе (более умном) может оказаться неверным.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...