PICC18 Bug

Привет!

Обнаружил ошибку в работе компилятора PICC-18 (v8.30), при использовании "signed char" в качестве индекса к массиву:

char buf [ 256 ] ;

void func () { signed char indx ; buf [ indx ] ++ ; }

Executing: "C:\Tools\HT-PIC18\BIN\PICC18.EXE" -C -E"communication.cce" "communication.c" -O"communication.obj" -Q -MPLAB -18F6621 -D32 -FDOUBLE -Zg9

-O -D32 -ASMLIST

622 003244 50D9 movf fsr2l,w,c 623 003246 EE0D F0F9 lfsr 0,_buf 624 00324A 26E9 addwf fsr0l,f,c 625 00324C 0E00 movlw 0 626 00324E 22EA addwfc fsr0h,f,c 627 003250 2AEF incf indf0,f,c 629 003252 0012 return

В коде отсутствует раширение знака на старший байт. Я поэкспериментировал, скажем если к индексу добавить смещение (даже ноль), то расширение знака появляется, если использовать в качестве индекса глобальную переменную, опять пропадает. Причём на самом то деле выгоднее всего было бы просто использовать адресацию plusw:

movf fsr2l,w,c lfsr 0,_buf incf plusw0,f,c return

Если кому-нибудь из зарегистированных пользователей не лень, киньте баг-репорт HI-TECH.

Александр Голов, Москва, snipped-for-privacy@mail.ru

Reply to
Alexander Golov
Loading thread data ...
Reply to
Alex Mogilnikov
Reply to
Nickita A Startcev

Привет!

Tue Mar 29 2005 16:10, Alex Mogilnikov wrote to Alexander Golov:

...

AG>> Обнаружил ошибку в работе компилятора PICC-18 (v8.30), при AG>> использовании "signed char" в качестве индекса к массиву:

AG>> char buf [ 256 ] ;

AG>> void func () AG>> { AG>> signed char indx ; AG>> buf [ indx ] ++ ; AG>> }

AM> Мне лень лезть в текст стандарта, но по-моему приведенный тобой код AM> дает неопределенное поведение. И если так, то анализировать результат AM> компиляции бессмысленно.

Что тут ещё за неопределённое поведение?

Александр Голов, Москва, snipped-for-privacy@mail.ru

Reply to
Alexander Golov

Привет!

Tue Mar 29 2005 15:32, Dima Orlov wrote to Alexander Golov:

...

DO> Могу лишь сказать, что V8.35PL3 ведет себя также,

Да, я читал багфиксы 8.35 там про это ни слова.

DO> только по-моему, он себя и должен так вести.

С чего это вдруг? Или арифметика со знаком уже стала подчиняться каким-то новым правилам? Но ладно, фиг с ним, пускай я не прав, но как тогда объясняется это:

char buf [ 256 ] ;

void func1 () { signed char indx ; buf [ indx + 0 ] ++ ; }

Великая разница, неправда ли? Однако же результат совсем иной (я не имею ввиду безумную оптимизацию, вернее её отсутствие, а именно, что теперь сложение ведётся по ожидавшимся мной правилам):

636 003240 0EF8 movlw low _buf 637 003242 6E00 movwf btemp 638 003244 0E0D movlw high _buf 639 003246 6E01 movwf btemp+1 640 003248 5000 movf btemp,w 641 00324A 24D9 addwf fsr2l,w,c 642 00324C 6EE9 movwf fsr0l,c 643 00324E 0E00 movlw 0 644 003250 BED9 btfsc fsr2l,7,c 645 003252 0EFF movlw 255 646 003254 2001 addwfc btemp+1,w 647 003256 6EEA movwf fsr0h 648 003258 2AEF incf indf0,f,c 650 00325A 0012 return

Теперь ещё раз, немного подвинем переменную по тексту:

char buf [ 256 ] ; signed char indx ;

void func2 () { buf [ indx + 0 ] ++ ; }

И что же мы наблюдаем? Опять никакого расширения знака:

658 00325C 010B movlb _indx shr (0+8) 659 00325E 0EF8 movlw low _buf 660 003260 25F7 addwf _indx& (0+255),w,b 661 003262 6EE9 movwf fsr0l,c 662 003264 6AEA clrf fsr0h,c 663 003266 0E0D movlw high _buf 664 003268 22EA addwfc fsr0h,f,c 665 00326A 2AEF incf indf0,f,c 667 00326C 0012 return

А если к объявление indx добавить near или far, опять всплывает предыдущий вариант кода. Так что баг в любом случае налицо, можно выбрать по вкусу, кому где больше нравится.

Александр Голов, Москва, snipped-for-privacy@mail.ru

Reply to
Alexander Golov

Привет!

Tue Mar 29 2005 23:40, Nickita A Startcev wrote to Alex Mogilnikov:

...

AG>>> Обнаружил ошибку в работе компилятора PICC-18 (v8.30), при AG>>> использовании "signed char" в качестве индекса к массиву:

AG>>> char buf [ 256 ] ;

AG>>> void func () AG>>> { AG>>> signed char indx ; AG>>> buf [ indx ] ++ ; AG>>> }

AM>> Мне лень лезть в текст стандарта, но по-моему приведенный тобой AM>> код дает неопределенное поведение. И если так, то анализировать AM>> результат компиляции бессмысленно.

NAS> signed имеет право завернуться после 0x7F,

Что значит форма "имеет право завернуться"? А что, "имеет право" и не завернуться?

NAS> при входе в функцию indx не NAS> инициализируется, при выходе не сохраняется. Так что тут аж две грабли NAS> потенциальных.

Господи, детский сад какой-то! Вы что, серьёзно считаете, что я привожу ту самую программу, в которой и всплыл данный баг? Естестевнно в реальном коде всё иницализировалось и использовалось, а здесь я специально сформировал предельно урезанную последовательность, генерирующую код, идентичный по проявлению бага тому, который был в реальной программе.

Александр Голов, Москва, snipped-for-privacy@mail.ru

Reply to
Alexander Golov
Reply to
Nickita A Startcev
Reply to
Alex Mogilnikov
Reply to
Alex Mogilnikov

Привет!

Wed Mar 30 2005 11:44, Nickita A Startcev wrote to Alexander Golov:

...

AG>>>>> Обнаружил ошибку в работе компилятора PICC-18 (v8.30), при AG>>>>> использовании "signed char" в качестве индекса к массиву:

...

NAS>>> signed имеет право завернуться после 0x7F,

AG>> Что значит форма "имеет право завернуться"? А что, "имеет право" и не AG>> завернуться?

NAS> Именно. Hа некоторых архитектурах допустимо "сложение с насыщением" и NAS> 0xAA+0xBB=0xFF при восьмибитной арифметике.

Не понимаю только какое всё это имеет отношене к данному случаю?

Александр Голов, Москва, snipped-for-privacy@mail.ru

Reply to
Alexander Golov

Привет!

Wed Mar 30 2005 08:58, Dima Orlov wrote to Alexander Golov:

...

DO> Присвоение беззнаковому типу знакового.

Здесь нет никаких присваиваний, а есть только одно неявное преобразование значения переменной indx типа signed char к значению индекса массива привычного для С типа int, который, кстати, является знаковым.

При этом замечу, что ничего неопределённого в действительном присвоении беззнаковому типу знакового компилятор не видит и делает всё ожидаемым образом:

void func3 () { unsigned int ptr ; signed char indx ; ptr = indx ; }

648 003256 50D9 movf fsr2l,w,c 649 003258 6EF3 movwf prodl,c 650 00325A 6AF4 clrf prodh,c 651 00325C BEF3 btfsc prodl,7,c 652 00325E 06F4 decf prodh,f,c 654 003260 0012 return

Александр Голов, Москва, snipped-for-privacy@mail.ru

Reply to
Alexander Golov

Привет!

Wed Mar 30 2005 08:58, Dima Orlov wrote to Alexander Golov:

...

DO> Да, у тебя вместо присвоения беззнаковому типу знакового получается DO> приесвоение беззнаковому типу результата операции между знаковым и не DO> помню каким (я всегда явно U к константам ставлю).

Интересная теория, вот только как она объяснит, что при добавлении к объявлению "signed char indx" квалификатора static всё опять возвращается к результату самого верхнего примера?

DO> Я не помню как стандарт разруливает подобные ситуации, но код-то явно DO> неправильный изначально.

Пока я не увидел ничего внятно показывающего неправильность кода. Индексирование знаковыми переменными не явлется неправильным с точки зрения C. Вообще переменные типа int в качестве индексов очень распространены, хотя обычно это приведение с одинаковой разрядностью. Но с таким же успехом допустимо и индексирование знаковыми char для систем с 16...32-разрядным адресом или short для 32-разрядным.

DO> Как минимум, отсутствие предупреждения...

Как раз в контексте предупреждений я не вижу никаких проблем. То же самое на Watcom 10.5:

0000 68 04 00 00 00 func1_ push 00000004H 0005 e8 00 00 00 00 call __CHK 000a 0f be c0 movsx eax,al 000d fe 80 00 00 00 00 inc byte ptr _buf[eax] 0013 c3 ret

то же самое на PIC30-GCC:

ee: 80 00 fb se.w w0, w1 f0: 03 00 20 mov.w #0x0, w3 f2: 61 c2 79 mov.b [w1+w3], w4 f4: 04 41 e8 inc.b w4, w2 f6: 82 f0 79 mov.b w2, [w1+w3] f8: 00 00 06 return

И всё без предупреждений, но главное -- работает ожидаемым образом.

Александр Голов, Москва, snipped-for-privacy@mail.ru

Reply to
Alexander Golov

Привет!

Wed Mar 30 2005 20:04, Alex Mogilnikov wrote to Alexander Golov:

...

AG>>>> void func () AG>>>> { AG>>>> signed char indx ; AG>>>> buf [ indx ] ++ ; AG>>>> }

AG>> Что тут ещё за неопределённое поведение?

AM> Использование неинициализированной автоматической переменной.

Не запрещено и уж конечно никакой непопределённости не вносит.

Александр Голов, Москва, snipped-for-privacy@mail.ru

Reply to
Alexander Golov

Привет!

Wed Mar 30 2005 20:08, Alex Mogilnikov wrote to Alexander Golov:

...

AG>> Господи, детский сад какой-то! Вы что, серьёзно считаете, что я AG>> привожу ту самую программу, в которой и всплыл данный баг? Естестевнно

AM> Просто странно взять код, для которого поведение компилятора AM> неопределено, и рассуждать, почему он повел себя так, а не иначе. :)

Это лишь твои фантазии.

AM> Hеопределенное поведение - это значит, что _любое_ поведение AM> компилятора не является багом. Вот последний приведенный тобой пример, AM> где переменная indx глобальная - это другое дело, тут поведение вполне AM> определено, и можно смотреть, соответствует ли ему сгенеренный AM> компилятором код или нет.

Ну посмотрел? И что выяснил?

Александр Голов, Москва, snipped-for-privacy@mail.ru

Reply to
Alexander Golov

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.