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

Прежде, чем писать новое, изучил в отладчике работу обеих моих программ - начальной si16toad и измененной itoa, в которой операции % и / были заменены вызовом библиотечной функции div. Напомню: Keil uVision - RealView MDK-ARM 4.10, STM32F103. Результаты оказались интересными.

 

После компиляции в окне Build Ouitput для обеих программ выдаются одинаковые размеры для кода - 548 байтов при оптимизации O0 и 536 байтов при оптимизации O3. Почему они одинаковые, не понимаю (см. ниже)?! Размеры данных всех типов тоже одинаковые вообще всегда, но это, как раз, не удивляет.

 

Посчитал размер обеих функций по листингу C компилятора (есть галочка в настройках генерировать листинг). При O0 для si16toad насчитал 84 байта, для itoa 98 байтов (не считая 14 байтов в самой функции div, это уже в отладчике увидел). При O3 - 80 байтов и 94 байта, соответственно. Причем, при оптимизации O0 в si16toad команда деления использовалась дважды, а при O3 только один раз. В-общем, мой первый вариант оказался компактнее.

 

Посчитал в отладчике количество тактов. Счетчик тактов виден в окне регистров, засекал значение перед вызовом своей функции и после нее. При O0 si16toad выполнялась за 171 такт, itoa за 232 такта. При O3 - 121 такт и 210 тактов, соответственно. Мой первый вариант оказался еще и быстрее.

 

Увидел лишние знаковые и беззнаковые расширения для переменных меньше 32 байтов. Вот здесь буду совершенствовать программу. Массив или указатель - тоже проверю. Заносить пробелы сразу - их, к сожалению, максимум 5 (не 4). Над этим и др. пока думаю.

 

 

 

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


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

Заносить пробелы сразу - их, к сожалению, максимум 5 (не 4). Над этим и др. пока думаю.

Их у Вас четыре. Можете попробовать на пальцах посчитать от X0 (раз-два) до X32768(раз-два-..шесть). Ну и размер должен быть на на уровне 60 байт, ну и тактов заметно менее.

 

 

 

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


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

Их у Вас четыре. Можете попробовать на пальцах посчитать от X0 (раз-два) до X32768(раз-два-..шесть). Ну и размер должен быть на на уровне 60 байт, ну и тактов заметно менее.

Перед "0" я символ + или - не ставлю (считаю, так "красивее" и "правильнее"), потому и обработка такая в начале программ. Итого _ _ _ _ _ 0 \0.

По поводу размеров и тактов - могу выдать весь проект в заархивированном виде.

В настройках есть какие-то "галочки", которых не трогал. Может, что-то и упустил...

Keil_Temp.zip

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


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

Перед "0" я символ + или - не ставлю

Вы ставите один из 3x символов. Вот и ставьте. Таки 4 :)

По поводу размеров и тактов - могу выдать весь проект в заархивированном виде.

Я говорю об аккуратно написанном, посему про 80 байтов в Вашем варианте верю. Сделайте 60 :).

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


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

2 zltigo

Непременно. :)

Выставил две "галки" - Use Cross-Module Optimization и Use MicroLIB. Общий размер кода сократился до 212 и 324 байтов для первой и второй программ. Причем, такой размер получается со второго раза компиляции. "Все чудесатее и чудесатее." Что эти параметры делают? А на конкретный размер и состав кода пока не смотрел.

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


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

void  itoad(int number, uint8_t *string)
{
  uint8_t  sign;
  *(int32_t *) string =       ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24;
  *(int32_t *)(string + 4) =  ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24;  
  *(int32_t *)(string += 8) = ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24;
  if (!number) return;
  if (number > 0) sign = '+';
  else {
    number = -number;
    sign = '-';
  }
  string += 2;
  do {
    *string-- = number % 10 + '0';
  } while (number /= 10);
  *string = sign;
}

Работает с 32-битовыми числами со знаком.

string должна быть 12 байтов для 32-битового числа.

60 байтов (+ 4 байта хранят константу "_ _ 0").

~207 тактов.

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


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

 *(int32_t *) string =

Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные.

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


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

Знатная грабля

А для Cortex-M3? А как надо по вашему мнению?

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


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

Знатная грабля. Исключение при первой же string, начало которой не попадает на границу 4 байт. Или просто порушенные соседние данные.

Это гнулось под Cortex - такая вот игра.

60 байтов

Чуть симпатичнее и скорее всего еще короче:

void  itoad(int number, uint8_t *string)
{
  uint8_t  sign;
  *(uint32_t *) string =       '    ';
  *(uint32_t *)(string + 4) =  '    ';  
  *(uint32_t *)(string += 10) = (uint32_t )"  0";
  if (!number) return;
  if (number > 0) sign = '+';
  else {
    number = -number;
    sign = '-';
  }
//  string += 2;
  do {
    *string-- = number % 10 + '0';
  } while (number /= 10);
  *string = sign;
}

Осталось первоначальную 16bit оптимизировать.

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


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

*(uint32_t *) string = ' ';

*(uint32_t *)(string + 4) = ' ';

Осталось первоначальную 16bit оптимизировать.

Кавычки не двойные?

Из этой 16-битов автоматически получается, если малое число использовать и буфер соответствующий.

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


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

Кавычки не двойные?

В первых двух - нет. Возможны warnings, правда, поскольку символ wide получается ИЗ 4x ПРОБЕЛОВ. А так нормально. В третьей - три символа в двойных.

Из этой 16-битов автоматически получается, если малое число использовать и буфер соответствующий.

Автоматически, не значит оптимально.

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


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

  *(uint32_t *)(string += 10) = (uint32_t )"  0";

Так - нельзя, пропускается два байта.

С кавычками - понял, но варнинги... как бы удовлетворить требованиям компилятора?

#define  FOUR_SPACES  0x20202020
*(uint32_t *) string = FOUR_SPACES;

Нормально?

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


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

Так - нельзя, пропускается два байта.

А, да. Что-то ошибся.

Тогда так:

  *(uint32_t *)(string += sizeof(int32_t)) =  '    ';  
  *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )"  0";
  string += 2;

Есть шанс на экономию пары байт.

 

С кавычками - понятно, но варнинги... как бы удовлетворить требованиям компилятора?

Ну, например, отключить их локально прагмой, либо таки (long)" ", но константа займет 8 байт.

 

 

 

Нормально?

Да.

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


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

  *(uint32_t *)(string += sizeof(int32_t)) =  '    ';  
  *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )"  0";
  string += 2;

Есть шанс на экономию пары байт.

В смысле, прилепить string +=2 сразу к предыдущему выражению, использующему указатель? А, заменить +8 +2 на +4 +4 +2?

upd. Попробовал и так, и сяк, и +10, лучше не становится.

 

16-битовую хочу попробовать с применением формата 4.28, как у aaarrr. А с тем, что сделал для 32 битов, и не знаю, куда уж дальше "копать" для 16 битов. Я, собственно, с 16-битовой и возился, пока не увидел, что 32-битовая из нее получается практически "даром":)

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


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

В смысле, прилепить string +=2 сразу к предыдущему выражению, использующему указатель?

Вот как написано, так пробуйте.

что 32-битовая из нее получается практически "даром":)

Полагаю, что там есть как минимум один нюанс - не ухудшить шестнадцатибитовостью ну и чуть поджать за счет меньшего буфера.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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