Автор Тема: Микроконтроллер - как перспектива примочкостроения  (Прочитано 25383 раз)

0 Пользователей и 2 Гостей просматривают эту тему.

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
Ну вот.... А было так радостно от осознания наконец-то понятых возможностей  :( Понимаю возможную занятость, но сразу возникают 3 вопроса:
1) что такое "стековая переменная"
2) почему это дурной тон?
3) а как же тогда?

Rst7

  • Сообщений: 1619
  • Мимо проходил...
    • Просмотр профиля
    • E-mail
Цитировать
Передавать в функцию указатели на стековые пременные считается дурным тоном.

Это еще почему??? О_о
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредствен

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
Ну только плиз не надо в аськах-личках перетирать!  ::) Если, конечно, не хотите сохранить тайну знания!  ::)

Rst7

  • Сообщений: 1619
  • Мимо проходил...
    • Просмотр профиля
    • E-mail
Тут наверное имелась в виду классическая жопа типа такого:
int *foo(void)
{
  int i=5;
  return &i;
}

Так это не передача, а возврат указателя на локальную переменную. Сие конечно есть жопа.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредствен

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
Не, ну эту жопу даже я понимаю :) Какая же это тогда жопа!  ;D Локальная переменная умерла после возврата из функции, а указатель не является ошибкой, но указывает.... на жопу  ;D

Думаю, имелось в виду нечто другое, посерьезнее...

KMG

  • Сообщений: 3776
    • ICQ клиент - 412221711
    • AOL клиент - Mike
    • Просмотр профиля
    • E-mail
Цитировать
Стековые объекты существуют лишь в границах содержащего их блока. При выходе за его пределы автоматически вызывается деструктор. Разумеется, получение адреса стекового объекта - дело рискованное, если только вы абсолютно, стопроцентно не уверены, что этот указатель не будет использован после выхода за пределы области действия объекта. Все фрагменты наподобие приведенного ниже всегда считаются потенциально опасными:

{
   int i;
   foo f;
   SomeFunction(&f);
}

Без изучения функции SomeFunction невозможно сказать, безопасен ли этот фрагмент.
SomeFunction может передать адрес дальше или сохранить его в какой-нибудь переменной, а по закону Мэрфи этот адрес наверняка будет использован уже после уничтожения объекта f. Даже если сверхтщательный анализ SomeFunction покажет, что адрес не сохраняется после вызова, через пару лет какой-нибудь новый программист модифицирует SomeFunction, продлит существование адреса на пару машинных команд и - БУМ!!! Лучше полностью исключить такую возможность и не передавать адреса стековых объектов.

PS я не сказал недопустимо, я говорил о дурном тоне, особенно в тимворке.
« Последнее редактирование: Ноября 02, 2011, 08:28:28 pm от mike »

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
Жопа из серии "объекта уже нет, а указатель остался и указывает на жопу"... Понятно, что этого надо избегать. Но остается 3-й вопрос - как же тогда?!  :-?

Rst7

  • Сообщений: 1619
  • Мимо проходил...
    • Просмотр профиля
    • E-mail
Цитировать
Без изучения функции SomeFunction невозможно сказать, безопасен ли этот фрагмент. SomeFunction может передать адрес дальше или сохранить его в какой-нибудь переменной

"Ну дай дураку в руки х.й стеклянный, он и вещь разобьет, и руки порежет." (ЦЭ) народная мудрость.

А вообще все эти писаки на тему "безопасного кода" ничего никогда не писали (в смысле программ). Так что не обращайте внимание, но всегда имейте четкое понимание возможных побочных эффектов функций. А то так можно договориться до того, что в классических функциях WinAPI ReadFile и WriteFile надо для возврата количества обработанных данных всегда заводить статическую переменную, а то вдруг  ;D

Цитировать
Но остается 3-й вопрос - как же тогда?! 

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

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail


Навскидку ничего более красочно характеризующее вышеописанную ситуацию не нашел :)

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
Вести с полей :) Спасибо за науку - переписал покрасивее. Только 1.5 момента: говорят, можно более красиво выделять 16-ричные разряды чем в лоб делением на 16, и второе - моя так горячо любимая функция int_to_string (которую я писал на ассемблере безо всяких сложностей - именно по такому же принципу как здесь) - не хочет вычислять при параметре >=int/2, хотя я делаю только вычитание! То есть, 32767 прожевывает, а 32768 - нет! Придется смотреть что там сделал компилятор  ::)
ЗЫ нет, мне конечно хватит и 32767, но хочется написать универсально на все времена  ::)
//-----------------------------------------------------------------------------------------------

char *int_to_string(char *s, int n)
{      
      int orders[] = {10000, 1000, 100, 10, 0};
      int *order = orders;
      char *begin = s;
      char digit;

      while(*order)
      {
            digit = 0;
            while (n >= *order)
            {
                  n = n - *order;
                  digit++;
            }
            if(digit || s!=begin) *s++ = '0' + digit;
            order++;
      }
      *s++ = '0' + n;

      return s;
}
//-----------------------------------------------------------------------------------------------

char *GPS_end_of_string(char *begin, char *end)
{      
      char *d;
      char chek_summ = 0;

      for(d=begin+1; d<end; d++) chek_summ = chek_summ^*d;

      *d++ = GPS_char_multiply;
      *d++ = '0' + chek_summ/16;
      *d++ = '0' + (chek_summ - 16*(chek_summ/16));
      *d++ = GPS_char_enter;
      *d++ = GPS_char_return;
      *d++ = 0;

      return d;
}
//-----------------------------------------------------------------------------------------------

void GPS_send_command_RMC_call_freq(int call_freq)
{
      //$PMTK314,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2D<CR><LF>
      
      char i;
      char *d = GPS_command_buffer;

      *d++='$';*d++='P';*d++='M';*d++='T';*d++='K';*d++='3';*d++='1';*d++='4';*d++=',';*d++='0';*d++=',';

      d = int_to_string(d, call_freq);

      for (i=0; i<17; i++)
      {
            *d++ = ',';
            *d++ = '0';
      }

      GPS_end_of_string(GPS_command_buffer, d);
}      
//-----------------------------------------------------------------------------------------------

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
Написал
char *int_to_string(char *s, unsigned int n)и все заработало. А я как наивный чукотский парень думал что по умолчанию всегда unsigned  ::)

Rst7

  • Сообщений: 1619
  • Мимо проходил...
    • Просмотр профиля
    • E-mail
Я еще вот что рекомендую. Вот это
int orders[] = {10000, 1000, 100, 10, 0};
стоит сделать хотя бы static int.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредствен

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
Я догадывался, что надо с этим фактически константным массивом что-то такое написать, чтобы это явно показать. Но я по глупости написал const, компилятор заругался и я решил оставить эту затею :)

ЗЫ надо бы расписать на бумажке на досуге какие бывают переменные и области их видимости и действия. Например, командир мне недавно открыл глаза на то, что если я определяю константный массив - от пишется во флеш, но при компиляции создается его КОПИЯ В ОЗУ, с которой и происходит работа! Но есть какие-то хитрые директивы из центра, которые позволяют НЕ СОЗДАВАТЬ эту копию, а работать с константами напрямую читая их из флеша  ::) А у меня в этом проекте как раз ОЗУ мало, а длинных строковых констант много :)

Rst7

  • Сообщений: 1619
  • Мимо проходил...
    • Просмотр профиля
    • E-mail
Для GCC в инкарнации для AVR курите тут - http://www.nongnu.org/avr-libc/user-manual/pgmspace.html

Через жопу, конечно, я бы только из-за этого использовал бы IAR.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредствен

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
- сыночек, да чтож ты суп-то руками!....
- кто обкурился? Я обкурился?!
 ;D Это я к тому, что буду курить, спасибо  :)

Rst7

  • Сообщений: 1619
  • Мимо проходил...
    • Просмотр профиля
    • E-mail
Кстати, если в проце есть аппаратный умножитель, то довольно быстро (скорее всего с меньшим количеством накладных расходов) можно получить итерации так
unsigned short order=10000;
...
...
order=(((unsigned long)order*6554)>>16);
...

Правда, там тонкость, эта штука вместо последнего 0 дает 1, так что надо изменить проверку.
« Последнее редактирование: Ноября 03, 2011, 10:50:54 am от Rst7 »
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредствен

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
:) Если уж совсем честно, то в целях минимизации
Цитировать
накладных расходов
в свое время на ассемблере я даже массив не заводил и порядки в него не засовывал :) Я просто определил 4 числовые константы: 10000, 1000, 100 и 10 и 4 одинаковые короткие секции asm кода у меня шли подряд и дублировались - а в каждом я вычитал из регистра константу :) Так же можно было бы и тут написать - это я просто сделал "по-программистски", с претензией на масштабируемость :)

ЗЫ а поначалу я на asm тоже получал каждый порядок перемножением 10-к (через сложение, естественно :) ), но овчинка выделки не стоила :)

ЗЗЫ я сейчас пытаюсь массив порядков во флеш засунуть и оттуда читать :)
Цитировать
зачем внутри кода считать то, что можно посчитать заранее?
(С) командир  ::)
« Последнее редактирование: Ноября 03, 2011, 11:09:40 am от Ivana »

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
В Вашем последнем коде я правильно догадываюсь, что директива
(unsigned long)относится к результату операции
order*6554и таким образом приводит этот результат к указанному типу - unsigned long? Единицу то потом можно прибавить, только лучше ПЕРЕД вычитанием каждого порядка - я правильно догадываюсь, чтобы в минус не залезть?  ::)

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
Попробовал так сделать на С и посмотреть что сделает компилятор - вроде все правильно, CP/CPC и т.д., но что-то не лаконично :) У меня это выглядело вот так (кусок из общего кода)
; для десятичной системы исчисления

      .equ      _SI_order                        = 10            ; для десятичной системы исчисления при выводе результатов
      ;.equ      _max_length_SI                  = 5                  ; макс. разрядность чисел в _SI_order

      .equ      _SI_order_0                        = 1
      .equ      _SI_order_1                        = _SI_order
      .equ      _SI_order_2                        = _SI_order_1*_SI_order_1
      .equ      _SI_order_3                        = _SI_order_2*_SI_order_1
      .equ      _SI_order_4                        = _SI_order_3*_SI_order_1

.............................................................
.............................................................
.............................................................


;;--------------------------------------------------------------------

DECIMAL_value_KOI_8:

      ; _r_t1_hb:_r_t1_lb - остаток от числа, _SI_order-ичный разряд которого надо получить
      ; _r_count_measure_time_hb:_r_count_measure_time_lb - число _SI_order в нужной степени
      ; результат - в _r_transmit_data (и уже +$30 к цифре для получения её кода KOI-8)

      clr            _r_transmit_data

      DECIMAL_value_KOI_8_1:

      cp            _r_t1_lb, _r_count_measure_time_lb
      cpc            _r_t1_hb, _r_count_measure_time_hb
      brlo      DECIMAL_value_KOI_8_END
      sub            _r_t1_lb, _r_count_measure_time_lb
      sbc            _r_t1_hb, _r_count_measure_time_hb
      inc            _r_transmit_data
      rjmp      DECIMAL_value_KOI_8_1

      DECIMAL_value_KOI_8_END:

      ldi            _r_mom, $30                        ; свиг для кода KOI-8 цифры
      add            _r_transmit_data, _r_mom

      ret
;--------------------------------------------------------------------

.............................................
.............................................
.............................................


;--------------------------------------------------------------------

VALUE_transmit_RS232:

      ;_r_t1_hb:_r_t1_lb - на комп по RS232 в десятичной системе с запятой
      ;_r_count_measure_time_hb:_r_count_measure_time_lb - _SI_order
      ;_r_transmit_data - который потом шлем на комп по RS232

      ldi            _r_count_measure_time_lb, low(_SI_order_4)
      ldi            _r_count_measure_time_hb, high(_SI_order_4)
      rcall       DECIMAL_value_KOI_8
      rcall       DATA_transmit_RS232

      ldi            _r_count_measure_time_lb, low(_SI_order_3)
      ldi            _r_count_measure_time_hb, high(_SI_order_3)
      rcall       DECIMAL_value_KOI_8
      rcall       DATA_transmit_RS232

      ldi            _r_count_measure_time_lb, low(_SI_order_2)
      ldi            _r_count_measure_time_hb, high(_SI_order_2)
      rcall       DECIMAL_value_KOI_8
      rcall       DATA_transmit_RS232

      ; запятая
      ldi            _r_transmit_data, KOI_8_comma
      rcall       DATA_transmit_RS232

      ldi            _r_count_measure_time_lb, low(_SI_order_1)
      ldi            _r_count_measure_time_hb, high(_SI_order_1)
      rcall       DECIMAL_value_KOI_8
      rcall       DATA_transmit_RS232

      ldi            _r_count_measure_time_lb, low(_SI_order_0)
      ldi            _r_count_measure_time_hb, high(_SI_order_0)
      rcall       DECIMAL_value_KOI_8
      rcall       DATA_transmit_RS232

      ret
;--------------------------------------------------------------------

ivana

  • Сообщений: 3
  • GtLab.Net forever!
    • Просмотр профиля
    • E-mail
Поигрался ещё - это попытка сделать аналогию с asm... Только тут остаток от исходного числа передается по ссылке через ОЗУ, а в примере выше - насквозь через регистр :) В той задаче я, кстати, вообще умудрился обойтись без ОЗУ, но 8-битных регистров хватило почти впритык  ;D

//-----------------------------------------------------------------------------------------------

char count_of_order(unsigned int *n, unsigned int order)
{
      char res = 0;

      while (*n >= order)
      {
            *n = *n - order;
            res++;
      }

      return res;
}
//-----------------------------------------------------------------------------------------------


char *int_to_string(char *s, unsigned int n)//n_value)
{      
      char *begin = s;
      char digit;
      //unsigned int n = n_value; зараза, так тоже работает,
//используя указатель не на внутреннюю переменную а на входящий параметр :)


      if((digit = count_of_order(&n, 10000))      || s!=begin) *s++ = '0' + digit;
      if((digit = count_of_order(&n, 1000))      || s!=begin) *s++ = '0' + digit;
      if((digit = count_of_order(&n, 100))       || s!=begin) *s++ = '0' + digit;
      if((digit = count_of_order(&n, 10))       || s!=begin) *s++ = '0' + digit;

      *s++ = '0' + n;

      return s;
}
//-----------------------------------------------------------------------------------------------
« Последнее редактирование: Ноября 03, 2011, 12:47:20 pm от Ivana »