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

 
 
> Несимметрия конечного результата vinavr компилятора
=GM=
сообщение Nov 16 2012, 21:46
Сообщение #1


Ambidexter
*****

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



Всем привет.
Такой вопрос. Почему код
Код
  while(pph!=&ph[8])
  {
   *(pph++)=~(*(pph-4));
  },

в котором берётся часть массива, инвертируется и записывается в другое место, компилируется в такой несимметричный код?
Код
  while(pph!=&ph[8])
  {
   *(pph++)=~(*(pph-4));
  94:    fd 01           movw    r30, r26
  96:    34 97           sbiw    r30, 0x04; 4
  98:    80 81           ld    r24, Z
  9a:    80 95           com    r24
  9c:    8c 93           st    X, r24
  9e:    80 91 71 00     lds    r24, 0x0071
  a2:    80 95           com    r24
  a4:    11 96           adiw    r26, 0x01; 1
  a6:    8c 93           st    X, r24
  a8:    11 97           sbiw    r26, 0x01; 1
  aa:    90 91 72 00     lds    r25, 0x0072
  ae:    89 2f           mov    r24, r25
  b0:    80 95           com    r24
  b2:    12 96           adiw    r26, 0x02; 2
  b4:    8c 93           st    X, r24
  b6:    12 97           sbiw    r26, 0x02; 2
  b8:    80 91 73 00     lds    r24, 0x0073
  bc:    80 95           com    r24
  be:    13 96           adiw    r26, 0x03; 3
  c0:    8c 93           st    X, r24
  }

Казалось бы чего проще, для всех 4-х байт сделать одно и тоже действие: загрузить байт
в регистр, а лучше бы воспользоваться регистровой парой Z, инвертировать и записать в
новое место, указываемое парой Х. Дальше, почему бы не использовать постинкремент Х+
вместо двух команд adiw и st? Может, кто-то знает, как переделать си-код в нечто подобное?


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 37)
Genadi Zawidowsk...
сообщение Nov 16 2012, 23:19
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



-Os, gcc 4.7.2
Код
000066a2 <testfn>:
    66a2:       e2 e9           ldi     r30, 0x92    ; 146
    66a4:       f3 e0           ldi     r31, 0x03    ; 3
    66a6:       df 01           movw    r26, r30
    66a8:       14 97           sbiw    r26, 0x04    ; 4
    66aa:       8c 91           ld      r24, X
    66ac:       80 95           com     r24
    66ae:       81 93           st      Z+, r24
    66b0:       83 e0           ldi     r24, 0x03    ; 3
    66b2:       ea 39           cpi     r30, 0x9A    ; 154
    66b4:       f8 07           cpc     r31, r24
    66b6:       b9 f7           brne    .-18         ; 0x66a6 <testfn+0x4>
    66b8:       08 95           ret


Код
static unsigned char ph [8];
void
__attribute__ ((used))
testfn(void)
{
unsigned char * pph = ph;
  while(pph!=&ph[8])
  {
   *(pph++)=~(*(pph-4));
  };
}


Цитата
vinavr компилятора

Отвечая на Ваш вопрос... Меня давно удивляла неоптимальность применявшихся конструкций в winavr. В этом году, к счастью, появились компиляторы из более новых версий gcc. winavr (проект с таким именем на соурсфоргеекс) последний рз обновлялся тогда, когда такие оптимизайии для avr не делались - потому для вашей задачи как переделать си-код в нечто подобное используйте компилятор поновее.

Сообщение отредактировал Genadi Zawidowski - Nov 16 2012, 23:26
Go to the top of the page
 
+Quote Post
zombi
сообщение Nov 16 2012, 23:44
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Писать на CИ и надеятся что какие то "дяди" должны за Вас выполнить оптимизацию??? наивно!!!
Пишу на асме всегда сам всё оптимизирую и всегда знаю что и за какое время выполняется.

Цитата(=GM= @ Nov 17 2012, 00:46) *
Может, кто-то знает, как переделать си-код в нечто подобное?

biggrin.gif На ассемблере писать!
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 17 2012, 06:14
Сообщение #4


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Текст, взятый у Геннадия, дает
CODE
static unsigned char ph [8];
void
__attribute__ ((used))
testfn(void)
{
7e: ec e5 ldi r30, 0x5C; 92
80: f0 e0 ldi r31, 0x00; 0
unsigned char * pph = ph;
while(pph!=&ph[8])
{
*(pph++)=~(*(pph-4));
82: 81 91 ld r24, Z+
84: 80 95 com r24
86: 83 83 std Z+3, r24; 0x03
void
__attribute__ ((used))
testfn(void)
{
unsigned char * pph = ph;
while(pph!=&ph[8])
88: 80 e0 ldi r24, 0x00; 0
8a: e4 36 cpi r30, 0x64; 100
8c: f8 07 cpc r31, r24
8e: c9 f7 brne .-14 ; 0x82 <testfn+0x4>
{
*(pph++)=~(*(pph-4));
};
}
90: 08 95 ret

-Os
avr-gcc 4.5.3 линух

Сообщение отредактировал _Pasha - Nov 17 2012, 06:15
Go to the top of the page
 
+Quote Post
С_Ч
сообщение Nov 17 2012, 06:57
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 22-10-12
Из: г. Москва
Пользователь №: 74 038



Цитата(zombi @ Nov 17 2012, 02:44) *
Писать на CИ и надеятся что какие то "дяди" должны за Вас выполнить оптимизацию??? наивно!!!
Пишу на асме всегда сам всё оптимизирую и всегда знаю что и за какое время выполняется.


biggrin.gif На ассемблере писать!

Золотые слова!
Go to the top of the page
 
+Quote Post
=GM=
сообщение Nov 17 2012, 07:30
Сообщение #6


Ambidexter
*****

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



Да, слова золотые, целиком и полностью поддерживаю. Только они никак не отвечают на мой вопрос.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 17 2012, 07:57
Сообщение #7


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Возьмите Клёновскую сборку, не обязательно крайнюю. Все-таки уже почти два года сабжу...
UPD: даже не два, а три года!

Сообщение отредактировал _Pasha - Nov 17 2012, 09:49
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 17 2012, 09:02
Сообщение #8


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(_Pasha @ Nov 17 2012, 09:57) *
Возьмите Клёновскую сборку, не обязательно крайнюю. Все-таки уже почти два года сабжу...
Или её, или, для win32, отсюда

Тот же тест, что выше.
Ubuntu 10.04, avr-gcc v 4.3.4 (т.е. тоже не слишком новая версия) -- код как у 4.5.3 выше.
avr-gcc -Os -S -mmcu=atmega8 testfn.c
Код
testfn:
    ldi r30,lo8(ph-4)
    ldi r31,hi8(ph-4)
    rjmp .L2
.L3:
    ld r24,Z
    com r24
    std Z+4,r24
    adiw r30,1
.L2:
    ldi r24,hi8(ph+4)
    cpi r30,lo8(ph+4)
    cpc r31,r24
    brne .L3
    ret

В той же убунте 4.7.0 (Klen-20110813) и 4.7.1 код как у Геннадия выше.

-O2 не отличается от -Os для всех вариантов.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
polyname
сообщение Nov 17 2012, 12:31
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 147
Регистрация: 18-05-12
Пользователь №: 71 915



Цитата
На ассемблере писать!
не, лучше прямо в бинарник
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 17 2012, 12:47
Сообщение #10


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(ReAl @ Nov 17 2012, 13:02) *
Или её, или, для win32, отсюда
+1 Использую avr-gcc-4.7.2. Очень доволен. Есть масса вкусностей: LTO, uint24, __flash и много-много другого...
тыц
тыц2
тыц3


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Nov 17 2012, 12:51
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Код
*(pph++)=~(*(pph-4));
  94:    fd 01           movw    r30, r26
  96:    34 97           sbiw    r30, 0x04; 4
  98:    80 81           ld    r24, Z
  9a:    80 95           com    r24
  9c:    8c 93           st    X, r24
  9e:    80 91 71 00     lds    r24, 0x0071
  a2:    80 95           com    r24
  a4:    11 96           adiw    r26, 0x01; 1
  a6:    8c 93           st    X, r24
  a8:    11 97           sbiw    r26, 0x01; 1
  aa:    90 91 72 00     lds  .....

Взять всю эту бурду выкинуть , написать на asm и вставить на место . А компилировать hex уже из asm


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
С_Ч
сообщение Nov 17 2012, 13:27
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 22-10-12
Из: г. Москва
Пользователь №: 74 038



Цитата(polyname @ Nov 17 2012, 15:31) *
не, лучше прямо в бинарник

А чем лучше? А то я чего-то отстал от жизни.
Для топикстартера. Вы же сами описали алгоритм. вот и напишите его на ассемблере и сделайте втавку. А если у вас не критично время выполнения, так и пусть процессор петляет. Вы думаете это единственное такое место? Не надо заглядывать в коды, работает и ладно. biggrin.gif
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Nov 17 2012, 14:11
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Цитата
А то я чего-то отстал от жизни.
нет , просто человек не любит asm


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
=GM=
сообщение Nov 17 2012, 15:28
Сообщение #14


Ambidexter
*****

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



Это я всё могу сделать на асме и сделаю, здесь проблем нет, хотя инлайновый асм в винавре это нечто. Приведенный в первом посте код - это часть прерывания, которая формирует фазы ЖКИ. Скорости там небольшие, но хотелось бы, чтобы все фазы были симметричны по длительности исполнения, иначе возникнет постоянный микроток через ЖК, который в итоге приведёт к разрушению ЖК. Опять же, 3-4 года назад мне здесь же на форуме все уши прожужжали, как хорошо писать на си, я проникся, стал писать, вот результат. Теперь опять призывают писать на асме. Ну, надо быть последовательными, граждане-братцы...


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 17 2012, 15:43
Сообщение #15


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(=GM= @ Nov 17 2012, 18:28) *
Ну, надо быть последовательными, граждане-братцы...

А Вы не слушайте кого ни попадя! sm.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 17 2012, 17:42
Сообщение #16


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (=GM= @ Nov 17 2012, 17:28) *
могу сделать на асме и сделаю, здесь проблем нет, хотя инлайновый асм в винавре это нечто.
Но желание потроллить не дает покоя.
То, что в качестве вброса использовался компилятор почти трехлетней давности автора не смущает, а то, что при грамотном использовании инлайн-асм gcc позволяет сделать практичеки чудеса - это для слабых...


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
=GM=
сообщение Nov 17 2012, 19:42
Сообщение #17


Ambidexter
*****

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



Борщ, уймитесь. Мне этот топик был полезен, уже скачал avr-gcc-4.7.2-mingw32, спасибо неозабоченным коллегам.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 17 2012, 20:37
Сообщение #18


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



А нельзя ли уточнить, какая именно версия avr-gcc/WinAVR сгенерировала код из первого сообщения blink.gif ?
И с какими ключами blink.gif ?

А то я вот поднял виртуалку, в которой я виндовые компиляторы на scmRTOS гоняю, у меня там подборка анитквариата есть. Полез вглубь.

WinAVR-20100110 (avr-gcc 4.3.3)
Код
testfn:
    ldi r30,lo8(ph-4)
    ldi r31,hi8(ph-4)
    rjmp .L2
.L3:
    ld r24,Z
    com r24
    std Z+4,r24
    adiw r30,1
.L2:
    ldi r24,hi8(ph+4)
    cpi r30,lo8(ph+4)
    cpc r31,r24
    brne .L3
    ret


WinAVR-20081205 (avr-gcc 4.3.2)
Код
testfn:
    ldi r30,lo8(ph-4)
    ldi r31,hi8(ph-4)
    rjmp .L2
.L3:
    ld r24,Z
    com r24
    std Z+4,r24
    adiw r30,1
.L2:
    ldi r24,hi8(ph+4)
    cpi r30,lo8(ph+4)
    cpc r31,r24
    brne .L3
    ret


WinAVR-20070525 (avr-gcc 4.1.2)
Код
testfn:
    ldi r30,lo8(ph-4)
    ldi r31,hi8(ph-4)
.L2:
    ld r24,Z
    com r24
    std Z+4,r24
    adiw r30,1
    ldi r24,hi8(ph+4)
    cpi r30,lo8(ph+4)
    cpc r31,r24
    brne .L2
    ret


WinAVR-20060421 (avr-gcc 3.4.6)
Код
testfn:
    ldi r30,lo8(ph)
    ldi r31,hi8(ph)
.L4:
    sbiw r30,4
    ld r24,Z
    adiw r30,4
    com r24
    st Z+,r24
    ldi r24,hi8(ph+8)
    cpi r30,lo8(ph+8)
    cpc r31,r24
    brne .L4
    ret

Это все с -Os, для пары версий глянул с -O2 -- то же самое.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
=GM=
сообщение Nov 17 2012, 21:58
Сообщение #19


Ambidexter
*****

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



WinAVR-20100110 (AVR-Studio, vers.4.18, build 684, GUI vers.4.18,0,680)
Ключ -Os


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 18 2012, 09:35
Сообщение #20


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Да студия по барабану, если ключ оптимизации известен.
Ну 20100110 я ж первой проверил. Практически от 3.4.6 до 4.7.1 на этом тесте результат одинаков по объёму, разница в деталях реализации.
Возможно, там вокруг что-то было, что поломало потмизацию, но всё равно непонятно.
Можно больший по размеру фрагмент кода, внутри которого этот цикл?


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Petka
сообщение Nov 18 2012, 10:33
Сообщение #21


Профессионал
*****

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(ReAl @ Nov 18 2012, 13:35) *
....
Возможно, там вокруг что-то было, что поломало потмизацию, но всё равно непонятно.
Можно больший по размеру фрагмент кода, внутри которого этот цикл?

Наверняка там всё volatile.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 19 2012, 06:52
Сообщение #22


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Мне вообще представленная ТС строка не нравится
Цитата(=GM= @ Nov 17 2012, 01:46) *
*(pph++)=~(*(pph-4));

приходится напрягать мозг чтобы понять что произойдёт тут и вспоминать точки следованияsad.gif
ИМХО так значительно прозрачнее
Код
pph[0] = ~pph[-4];
pph++;
ну или даже так
Код
*pph++ = ~pph[-4]
не, так плохо, прогнал, и на компиляции получил предупреждение о возможном неопределённом поведении. {дополнено позже}
Цитата(Сергей Борщ @ Nov 17 2012, 21:42) *
при грамотном использовании инлайн-асм gcc позволяет сделать практичеки чудеса
Это наверно так, но у меня к примеру почему-то простейшая конструкция не выходит (правда я нашёл другой способ решить мою задачу)
Код
#define makeword16(b0,b1)                                                     \
(__extension__({                                                              \
    uint8_t  __b0 = (uint8_t)(b0);                                            \
    uint8_t  __b1 = (uint8_t)(b1);                                            \
    uint16_t __result;                                                        \
    __asm__ __volatile__                                                      \
    (                                                                         \
        "\n\t"                                                                \
        "mov %A0,%A1"                       "\n\t"                            \
        "mov %B0,%A2"                       "\n\t"                            \
        : "=r" (__result)                   /* output operands */             \
        : "r" (__b0),                       /* input operands */              \
          "r" (__b1)                                                          \
    );                                                                        \
    __result;                                                                 \
}))

uint8_t b[n];
uint16_t x = makeword16(b[1],b[0]); //read big-endian value
...

получаем
Код
     582:    81 81           ldd    r24, Z+1; 0x01
     584:    90 81           ld    r25, Z
     586:    88 2f           mov    r24, r24     // я плакал:(
     588:    99 2f           mov    r25, r25     // дважды:(
Если вы сможете мне помочь буду очень благодарен за развитие кругозора. Спасибо!


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Nov 20 2012, 01:29
Сообщение #23


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Цитата
понять что произойдёт тут и вспоминать точки следования

А неопределённый результат произойдёт. Я в данном случае не присматирвался к коду, а компилятор ругнулся как раз про это.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 20 2012, 07:35
Сообщение #24


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (demiurg_spb @ Nov 19 2012, 08:52) *
// я плакалsad.gif
Вы сами написали mov в своей вставке, вы его получили. Компилятор не виноват, что входные и выходные параметры были в одних и тех же регистрах. Как ему это объяснить - я пока не знаю. Эта ваша задача решается через union. Будет так же непортируемо, как и с асм-вставкой.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 20 2012, 07:40
Сообщение #25


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Сергей Борщ @ Nov 20 2012, 11:35) *
Эта ваша задача решается через union. Будет так же непортируемо, как и с асм-вставкой.
Так и сделано (с union наиоптимальнейший результат).
Но хотелось бы понять как сие и на асме изобразить. Сейчас не до портируемости, ибо размер сильно важен, а со сдвигами сильно плохо оптимизирует...
Код
uint16_t x = b0<<8 | b1;
никак не меньше 4 инструкций выходитsad.gif


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 20 2012, 10:25
Сообщение #26


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (demiurg_spb @ Nov 20 2012, 09:40) *
Но хотелось бы понять как сие и на асме изобразить.
Знаю, как убрать один из mov:
CODE
    __asm__ __volatile__                                                      \
    (                                                                         \
        "\n\t"                                                                \
        "mov %B0,%2"                        "\n\t"                            \
        : "=r" (__result)                   /* output operands */             \
        : "0" (__b0),                       /* input operands */              \
          "r" (__b1)                                                          \
    );                                                                        \
Как объяснить насчет второго - пока не придумал.
QUOTE (demiurg_spb @ Nov 20 2012, 09:40) *
а со сдвигами сильно плохо оптимизирует...
Увы, пока да.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 20 2012, 12:39
Сообщение #27


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Сергей Борщ @ Nov 20 2012, 14:25) *
Знаю, как убрать один из mov:
Остроумно. Я около этого варианта тоже крутился, но не додумался до такого.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
=GM=
сообщение Nov 20 2012, 15:37
Сообщение #28


Ambidexter
*****

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



Цитата(demiurg_spb @ Nov 19 2012, 06:52) *
1) Мне вообще представленная ТС строка не нравится *(pph++)=~(*(pph-4));

приходится напрягать мозг чтобы понять что произойдёт тут и вспоминать точки следованияsad.gif

2) ИМХО так значительно прозрачнее
Код
pph[0] = ~pph[-4];
pph++;


Моя версия компилятора даёт один и тот же ассемблерный код для обоих вариантов 1 и 2.

while(pph!=&ph[8])
{
*(pph++)=~(*(pph-4));
98: 80 91 70 00 lds r24, 0x0070
9c: 80 95 com r24
9e: 80 93 74 00 sts 0x0074, r24
a2: 80 91 71 00 lds r24, 0x0071
a6: 80 95 com r24
a8: 80 93 75 00 sts 0x0075, r24
ac: 80 91 72 00 lds r24, 0x0072
b0: 80 95 com r24
b2: 80 93 76 00 sts 0x0076, r24
b6: 80 91 73 00 lds r24, 0x0073
ba: 80 95 com r24
bc: 80 93 77 00 sts 0x0077, r24

И сначала мне больше понравилась ваша версия 2, поскольку никаких предупреждений не было, а в моём варианте было предупреждение: operation on pph may be undefined - операция с pph может быть неопределенной.

Но присмотревшись к коду, я понял к чему относится предупреждение. По си коду указатель pph в процессе исполнения кода увеличивается на 4, а в листинге указатель кода никак не участвует, поскольку там цикл развернут и применена прямая адресация! Поэтому компилятор предупреждает, что если вы будете использовать pph дальше, то содержимое указателя может быть отлично от того, на что вы рассчитывали. Я считаю, что лучше пусть будет предупреждение просто как напоминание, что может произойти в дальнейшем.

А чудеса с оптимизацией продолжаются. Из такого си кода, больше ничего нет

int main(void) //LCD test
{
unsigned char *pph;
unsigned char *pdg;
while(1)
{
pdg=&dig[0];
pph=&ph[4];
while(pph!=&ph[8])
{
*(pph++)=~(*(pph-4));
}
}
}

получается такой ассемблерный листинг

int main(void) //LCD test
{
5e: e4 e7 ldi r30, 0x74 ; 116
60: f0 e0 ldi r31, 0x00 ; 0
pph=&ph[4];
while(pph!=&ph[8])
{
*(pph++)=~(*(pph-4));
62: 34 97 sbiw r30, 0x04 ; 4
64: 80 81 ld r24, Z
66: 34 96 adiw r30, 0x04 ; 4
68: 80 95 com r24
6a: 81 93 st Z+, r24
}
while((pdg)!=&dig[4]);
pph=&ph[4];
while(pph!=&ph[8])
6c: 80 e0 ldi r24, 0x00 ; 0
6e: e8 37 cpi r30, 0x78 ; 120
70: f8 07 cpc r31, r24
72: b9 f7 brne .-18 ; 0x62 <main+0x4>
74: 34 97 sbiw r30, 0x04 ; 4
76: f5 cf rjmp .-22 ; 0x62 <main+0x4>

Умереть-не встать: теперь компилятор решил не разворачивать цикл while. Не могу понять, по какой причине меняется генерируемый код - по воле левой ноги компилятора или я делаю что-то не так?


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 20 2012, 16:31
Сообщение #29


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(=GM= @ Nov 20 2012, 19:37) *
Умереть-не встать: теперь компилятор решил не разворачивать цикл while. Не могу понять, по какой причине меняется генерируемый код - по воле левой ноги компилятора или я делаю что-то не так?

Имхо, на таких мизерных фрагментах, смеяться над компилятором не нужно. Побеждает то один вариант, то другой. Я думаю, если у Вас флеш будет заканчиваться, в программу войдет кусок наименьшего объема.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 20 2012, 20:51
Сообщение #30


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(=GM= @ Nov 20 2012, 17:37) *
И сначала мне больше понравилась ваша версия 2, поскольку никаких предупреждений не было, а в моём варианте было предупреждение: operation on pph may be undefined - операция с pph может быть неопределенной.

Но присмотревшись к коду, я понял к чему относится предупреждение. По си коду указатель pph в процессе исполнения кода увеличивается на 4, а в листинге указатель кода никак не участвует, поскольку там цикл развернут и применена прямая адресация! Поэтому компилятор предупреждает, что если вы будете использовать pph дальше, то содержимое указателя может быть отлично от того, на что вы рассчитывали. Я считаю, что лучше пусть будет предупреждение просто как напоминание, что может произойти в дальнейшем.
Нет, не так.
Перепишите цикл следующим образом
Код
while(pph!=&ph[8])
{
    *pph=~(*(pph-4));
    ++pph; // Ну или pph++
}
и убедитесь, что сообщение пропало, хотя указатель так же меняется.
Дело тут в том, что эффект от операции pph++ может быть сделан где угодно между уже упомянутыми точками следования.
И строка
Код
{   *pph++=~(*(pph-4));  }

имеет одинаковое право быть скомпилированной и как вышло, и так:
Код
{
   temp_ptr1 = pph
   pph = pph + 1    <- эта строка имеет право стоять где угодно в пределах от { до;
   temp_ptr2 = pph - 4
   temp_var1 = *temp_ptr2
   temp_var1 = ~temp_var1
   *temp_ptr1 = temp_var1
;
и на какой-то другой архитектуре это может оказаться выгоднее, например, по скорости исполнения.
С-шная строка та же, а результат разный. Стандарт такие места обозначил как undefined behaviour, так как попытка задать что-то жесткое может ухудшить оптимизацию в других местах.
Классика.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
=GM=
сообщение Nov 21 2012, 07:22
Сообщение #31


Ambidexter
*****

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



Не понимаю разницы, оба варианта псевдокода приведите, чтобы сравнить.

(Добавлено позже)
1) Здесь не могу согласиться с вашим высказыванием, что "эта строка имеет право стоять где угодно в пределах от { до;"
Эта строка не может стоять первой
{
temp_ptr1 = pph
pph = pph + 1 <- эта строка имеет право стоять где угодно в пределах от { до;
temp_ptr2 = pph - 4
temp_var1 = *temp_ptr2
temp_var1 = ~temp_var1
*temp_ptr1 = temp_var1
;

2) Для компилятора в таком коде *pph++=~(*(pph-4)); нет ничего неоднозначного. Судите сами. Берется значение по
адресу (pph-4), инвертируется, сохраняется по адресу (pph), затем адрес (pph) увеличивается на 1. Где тут неоднозначность?
Здесь компилятор даже предупреждения не может выставить.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Nov 21 2012, 20:44
Сообщение #32


Местный
***

Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126



2 =GM=
А вопрос применения МК с хадварной поддержкой LCD рассматривался???
Ну там... PIC какой... или STM8L ...
Или всё это только "мазохизма ради" ???
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 21 2012, 21:32
Сообщение #33


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(=GM= @ Nov 21 2012, 09:22) *
Эта строка не может стоять первой
Да, конечно, первой не может. Это я сгоряча.
Но все остальные положения допустимы. И посмотрите внимательно -- они не равноправны.

Цитата(=GM= @ Nov 21 2012, 09:22) *
2) Для компилятора в таком коде *pph++=~(*(pph-4)); нет ничего неоднозначного. Судите сами. Берется значение по
адресу (pph-4), инвертируется, сохраняется по адресу (pph), затем адрес (pph) увеличивается на 1. Где тут неоднозначность?
Здесь компилятор даже предупреждения не может выставить.
Но ведь выставил -- про неопределённый результат.

Он имеет право вычислить адрес получателя раньше, чем адрес источника. Для pph[0] = ~pph[4]; разницы в порядке вычислений нет и предупреждения нет.

Для Вашего варианта неоднозначность в том, что побочный эффект от вычисления адреса получателя (результат действия pph++) он имеет право занести назад в pph до того, как выполнит (pph-4).

Вот ещё на ту же тему.
Код
unsigned char a, b;
void foo()
{
        a ^= b ^= a ^= b;
}

Код
axorb.c: In function ‘foo’:
axorb.c:5: warning: operation on ‘a’ may be undefined

Та же причина -- в интервале точек следования есть две записи в а. И их порядок не определен. Даже если для конкретного контроллера и конкретного компилятора во всех «испытаниях» будет получаться одинаковый результат и именно тот, которого Вы ждете. Правильный результат -- частный случай неопределённого. Но без гарантий.

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


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
=GM=
сообщение Nov 22 2012, 04:15
Сообщение #34


Ambidexter
*****

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



Цитата(HHIMERA @ Nov 21 2012, 20:44) *
2 =GM=
А вопрос применения МК с хадварной поддержкой LCD рассматривался???
Ну там... PIC какой... или STM8L ...Или всё это только "мазохизма ради" ???

Всё началось отсюда, там на основе
сломанного электронного термометра был сделан пробник-минивольтметр.

Что касается других МК. На STM32F100 discovery писал программку вывода на ЛСД,
который стоит на плате, вот там просто исплевался! Не знаю, кто придумал такое
аппаратное двухмерное представление сегментов, возможно индусы, тогда я думал о
них гораздо лучше, чем они есть на самом деле, но ХУЖЕ просто невозможно придумать,
это даже не мазохизм, а примерно как ржавой тупой пилой самому пилить зажатые в
тисках гениталии.


Цитата(ReAl @ Nov 21 2012, 07:22) *
{
temp_ptr1 = pph
pph = pph + 1 <- эта строка имеет право стоять где угодно в пределах от { до;
temp_ptr2 = pph - 4
temp_var1 = *temp_ptr2
temp_var1 = ~temp_var1
*temp_ptr1 = temp_var1
;

Извините, Александр, с ходу не углядел, но третью строку вы неправильно представляете. Должно быть "temp_ptr2 = temp_ptr1-4", а не " temp_ptr2 = pph-4".

Кстати, порядок для операции присваивания вполне определённый - справа налево.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Nov 22 2012, 05:38
Сообщение #35


Местный
***

Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126



Цитата(=GM= @ Nov 22 2012, 08:15) *
Не знаю, кто придумал такое
аппаратное двухмерное представление сегментов, возможно индусы, тогда я думал о
них гораздо лучше

Возможно, они вот так шахматы и придумали... не суть...
Просто чего-то с ужасом подумалось, что следующим шагом будет попытка детерминирования
недетерминированного времени входа в прерывание... в борьбе за полную симметрию... так может всё-таки сразу... хардварно???
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 22 2012, 06:58
Сообщение #36


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(=GM= @ Nov 22 2012, 06:15) *
Извините, Александр, с ходу не углядел, но третью строку вы неправильно представляете. Должно быть "temp_ptr2 = temp_ptr1-4", а не " temp_ptr2 = pph-4".
Я всё написал правильно. Именно temp_ptr2 = pph-4.
И именно потому, что это один из допустимых вариантов, компилятор и выдаёт предупреждение udefined operation.

Цитата(=GM= @ Nov 22 2012, 06:15) *
Кстати, порядок для операции присваивания вполне определённый - справа налево.
Ага, щас™
Код
unsigned char A;
unsigned char foo()
{
    unsigned char temp;
    temp = A = 3;    // Сначала присвоили A, а потом temp ?
    return temp;
}

Код
foo:    
    ldi r24,lo8(3); таки сначала temp
    sts A,r24     ; потом A
    ret


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

Благодаря определённому порядку во все переменные заносятся величины, полученные вычислениями справа налево, но порядок занесения величин (между двумя точками следования) неопределён. В корректной программе всё нормально.
В некорректной, как в Вашем случае с указателями или как в той цепочке a ^= b ^= a ^= b; компилятор выдаёт предупреждение, что операции над той или иной переменной неопределены.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 22 2012, 09:38
Сообщение #37


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



В продолжение темы:
Код
PORTA=PORTB=PORTC=0;
может быть скомпилировано в:
Код
PORTC=0;
PORTB=PORTC;
PORTA=PORTB;
А чтение некоторых регистров из SFR иногда не проходит бесследно...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ReAl
сообщение Nov 22 2012, 20:01
Сообщение #38


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(ReAl @ Nov 22 2012, 08:58) *
но порядок занесения величин (между двумя точками следования) неопределён.
Да, чтобы два раза не вставать...

В качестве упреждения разных «фи, какой он этот С, вот в ассемблере всё однозначно» предлагаю любителям PDP-11 сказать, что будет результатом операций
Код
  MOV (R0)+, R0;  как бы p = *p++;
  MOV R0, -(R0);  как бы *--p = p;
и при этом сказать, для какой модели PDP-11/версии микрокода такой результат будет :-)
Я уже точно не помню (оно мне и не нужно было, просто когда-то как казус запомнилось, но потом в понимании сути UB помогло), возможно, какая-то из этих строк одинаково выполнялась на любой PDP-11, но одна из них точно выполнялась по разному.

Цитата(ReAl @ Nov 22 2012, 08:58) *
В корректной программе
В стандарте есть такое понятие «well-formed», «корректная» может и не самый лучший перевод, но у меня лучше не вышло.
Ещё там есть слова sequence point (точка следования), assignment expression (присваивающее выражение) и side effect (побочный эффект -- в частности, запись в левый операнд присваивающего выражения является побочным эффектом вычисления присваивающего выражения).
Там всё можно найти.

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


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 02:14
Рейтинг@Mail.ru


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