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

 
 
> Несимметрия конечного результата 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
 
Start new topic
Ответов
demiurg_spb
сообщение Nov 19 2012, 06:52
Сообщение #2


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

Группа: Свой
Сообщений: 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
=GM=
сообщение Nov 20 2012, 15:37
Сообщение #3


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
ReAl
сообщение Nov 20 2012, 20:51
Сообщение #4


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

Группа: Свой
Сообщений: 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
Сообщение #5


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

Сообщений в этой теме
- =GM=   Несимметрия конечного результата vinavr компилятора   Nov 16 2012, 21:46
- - Genadi Zawidowski   -Os, gcc 4.7.2 Код000066a2 <testfn>: ...   Nov 16 2012, 23:19
- - zombi   Писать на CИ и надеятся что какие то "дяди...   Nov 16 2012, 23:44
|- - С_Ч   Цитата(zombi @ Nov 17 2012, 02:44) Писать...   Nov 17 2012, 06:57
|- - =GM=   Да, слова золотые, целиком и полностью поддерживаю...   Nov 17 2012, 07:30
- - _Pasha   Текст, взятый у Геннадия, дает CODEstatic unsigned...   Nov 17 2012, 06:14
- - _Pasha   Возьмите Клёновскую сборку, не обязательно крайнюю...   Nov 17 2012, 07:57
|- - ReAl   Цитата(_Pasha @ Nov 17 2012, 09:57) Возьм...   Nov 17 2012, 09:02
|- - demiurg_spb   Цитата(ReAl @ Nov 17 2012, 13:02) Или её,...   Nov 17 2012, 12:47
- - polyname   ЦитатаНа ассемблере писать!не, лучше прямо в б...   Nov 17 2012, 12:31
|- - С_Ч   Цитата(polyname @ Nov 17 2012, 15:31) не,...   Nov 17 2012, 13:27
|- - =GM=   Это я всё могу сделать на асме и сделаю, здесь про...   Nov 17 2012, 15:28
|- - _Pasha   Цитата(=GM= @ Nov 17 2012, 18:28) Ну, над...   Nov 17 2012, 15:43
|- - Сергей Борщ   QUOTE (=GM= @ Nov 17 2012, 17:28) могу сд...   Nov 17 2012, 17:42
|- - =GM=   Борщ, уймитесь. Мне этот топик был полезен, уже ск...   Nov 17 2012, 19:42
- - ILYAUL   Код*(pph++)=~(*(pph-4)); ...   Nov 17 2012, 12:51
- - ILYAUL   ЦитатаА то я чего-то отстал от жизни. нет , прост...   Nov 17 2012, 14:11
- - ReAl   А нельзя ли уточнить, какая именно версия avr-gcc/...   Nov 17 2012, 20:37
|- - =GM=   WinAVR-20100110 (AVR-Studio, vers.4.18, build 684,...   Nov 17 2012, 21:58
- - ReAl   Да студия по барабану, если ключ оптимизации извес...   Nov 18 2012, 09:35
|- - Petka   Цитата(ReAl @ Nov 18 2012, 13:35) .... Во...   Nov 18 2012, 10:33
|- - Сергей Борщ   QUOTE (demiurg_spb @ Nov 19 2012, 08:52) ...   Nov 20 2012, 07:35
||- - demiurg_spb   Цитата(Сергей Борщ @ Nov 20 2012, 11:35) ...   Nov 20 2012, 07:40
||- - Сергей Борщ   QUOTE (demiurg_spb @ Nov 20 2012, 09:40) ...   Nov 20 2012, 10:25
||- - demiurg_spb   Цитата(Сергей Борщ @ Nov 20 2012, 14:25) ...   Nov 20 2012, 12:39
|- - _Pasha   Цитата(=GM= @ Nov 20 2012, 19:37) Умереть...   Nov 20 2012, 16:31
|- - HHIMERA   2 =GM= А вопрос применения МК с хадварной поддержк...   Nov 21 2012, 20:44
||- - =GM=   Цитата(HHIMERA @ Nov 21 2012, 20:44) 2 =G...   Nov 22 2012, 04:15
||- - HHIMERA   Цитата(=GM= @ Nov 22 2012, 08:15) Не знаю...   Nov 22 2012, 05:38
||- - ReAl   Цитата(=GM= @ Nov 22 2012, 06:15) Извинит...   Nov 22 2012, 06:58
||- - demiurg_spb   В продолжение темы:КодPORTA=PORTB=PORTC=0;может бы...   Nov 22 2012, 09:38
||- - ReAl   Цитата(ReAl @ Nov 22 2012, 08:58) но поря...   Nov 22 2012, 20:01
|- - ReAl   Цитата(=GM= @ Nov 21 2012, 09:22) Эта стр...   Nov 21 2012, 21:32
- - Genadi Zawidowski   Цитатапонять что произойдёт тут и вспоминать точки...   Nov 20 2012, 01:29


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

 


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


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