Intel4004 1 7 мая, 2022 Опубликовано 7 мая, 2022 (изменено) · Жалоба Случайно обнаружил что гарантированно рабочая программа вдруг начала зависать. Полез разбираться - выяснилось что компилятор вдруг начал генерить неправильный код при вычислении оператора % (остаток от деления). Достал из бэкапа исходники прошивки конца прошлого года, скомпилял - код неправильный. Достал бинарник сделанный полгода назад из этих-же исходников этим-же кейлом, дизассемблял - код правильный. Пример: data unsigned long XXX; data unsigned char YYY; void main (void) { XXX = 608UL; YYY = XXX % 60UL; } Компиляем, получаем такое: C:0x2BDA 7B3C MOV R3,#0x3C C:0x2BDC 7A00 MOV R2,#0x00 C:0x2BDE 7900 MOV R1,#0x00 C:0x2BE0 7800 MOV R0,#0x00 C:0x2BE2 AF1B MOV R7,0x1B C:0x2BE4 AE1A MOV R6,0x1A C:0x2BE6 AD19 MOV R5,0x19 C:0x2BE8 AC18 MOV R4,XXX(0x18) C:0x2BEA 121552 LCALL C?ULDIV(C:1552) ; Вот тут в R4567 мы имеем результат деления, а в R0123 остаток ; Дальше начинается чушь C:0x2BED CC XCH A,R4 C:0x2BEE CD XCH A,R5 C:0x2BEF CE XCH A,R6 C:0x2BF0 CF XCH A,R7 C:0x2BF1 8F1C MOV YYY(0x1C),R7 А полгода назад тот-же самый компилятор из того-же самого проекта делал такое: 15: YYY = XXX % 60UL; C:0x504B MOV R3, #0x3C C:0x504D MOV R2, #0x00 C:0x504F MOV R1, #0x00 C:0x5051 MOV R0, #0x00 C:0x5053 MOV R7, 0x1B C:0x5055 MOV R6, 0x1A C:0x5057 MOV R5, 0x19 C:0x5059 MOV R4, XXX(0x18) C:0x2BEA LCALL C?ULDIV(C:1552) C:0x505E XCH A, R4 C:0x505F MOV A, R0 C:0x5060 XCH A, R4 C:0x5061 XCH A, R5 C:0x5062 MOV A, R1 C:0x5063 XCH A, R5 C:0x5064 XCH A, R6 C:0x5065 MOV A, R2 C:0x5066 XCH A, R6 C:0x5067 XCH A, R7 C:0x5068 MOV A, R3 C:0x5069 XCH A, R7 C:0x506A MOV YYY(0x1C), R7 Опитимизация: 0 (т.е. без оптимизации) При оптимизации 3 и выше - код генерится правильный. Кейл снес полностью, поставил с нуля - не помогает. И вот мне интересно - это я чего-то не понимаю, или это санкционный подарочек от кейла? UPD. Кейл - последний. 9.60. Он у них уже два года как не обновлялся. Изменено 7 мая, 2022 пользователем Intel4004 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба 9 hours ago, Intel4004 said: . . . Кейл снес полностью, поставил с нуля - не помогает. . . . А почему на листинге выше физ-адреса разные. Размеры bin-образа прошивки для "правильного-старого" и "неправильного-нового" как отличаются ? Или только этим участком кода, что приведен выше ? Такая хрень могла быть вызвана тем, что в функцию передавалась явная, заранее просчитанная препроцессором значение-константа (ну как умножать на ноль, только для остатка) и даже без оптимизации компилятор "сэкономил" на этом "нуле". Отсадите вызов из проекта. Сравните генерируемый компилятором код в урезанном и полном проектах. (bin) "Закладка" . . . Когда "собирали" версию компилятора это было еще неактуально. Хотя триггер по дате вполне может быть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 240 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба 10 часов назад, Intel4004 сказал: data unsigned long XXX; data unsigned char YYY; void main (void) { XXX = 608UL; YYY = XXX % 60UL; } Компиляем, получаем такое: C:0x2BDA 7B3C MOV R3,#0x3C C:0x2BDC 7A00 MOV R2,#0x00 C:0x2BDE 7900 MOV R1,#0x00 C:0x2BE0 7800 MOV R0,#0x00 C:0x2BE2 AF1B MOV R7,0x1B C:0x2BE4 AE1A MOV R6,0x1A C:0x2BE6 AD19 MOV R5,0x19 C:0x2BE8 AC18 MOV R4,XXX(0x18) C:0x2BEA 121552 LCALL C?ULDIV(C:1552) ; Вот тут в R4567 мы имеем результат деления, а в R0123 остаток ; Дальше начинается чушь C:0x2BED CC XCH A,R4 C:0x2BEE CD XCH A,R5 C:0x2BEF CE XCH A,R6 C:0x2BF0 CF XCH A,R7 C:0x2BF1 8F1C MOV YYY(0x1C),R7 В чём именно "чушь"? И почему думаете что "неправильный"? Не вижу проблемы в результате компиляции. У вас результат (YYY) нигде не используется. Поэтому компилятор вправе полностью выкинуть код записи в него. А команда "MOV YYY(0x1C),R7" может вообще никак не относиться к этому делению. 10 часов назад, Intel4004 сказал: А полгода назад тот-же самый компилятор из того-же самого проекта делал такое: 15: YYY = XXX % 60UL; C:0x504B MOV R3, #0x3C C:0x504D MOV R2, #0x00 C:0x504F MOV R1, #0x00 C:0x5051 MOV R0, #0x00 C:0x5053 MOV R7, 0x1B C:0x5055 MOV R6, 0x1A C:0x5057 MOV R5, 0x19 C:0x5059 MOV R4, XXX(0x18) C:0x2BEA LCALL C?ULDIV(C:1552) C:0x505E XCH A, R4 C:0x505F MOV A, R0 C:0x5060 XCH A, R4 C:0x5061 XCH A, R5 C:0x5062 MOV A, R1 C:0x5063 XCH A, R5 C:0x5064 XCH A, R6 C:0x5065 MOV A, R2 C:0x5066 XCH A, R6 C:0x5067 XCH A, R7 C:0x5068 MOV A, R3 C:0x5069 XCH A, R7 C:0x506A MOV YYY(0x1C), R7 А это Вы выдрали из рабочего проекта, в котором YYY видимо используется после. 10 часов назад, Intel4004 сказал: И вот мне интересно - это я чего-то не понимаю, или это санкционный подарочек от кейла? Во-первых: тестовый пример нужно писать корректно: или обеспечивать использование YYY после деления; или использовать volatile для результата (а может ещё какие-то префиксы; в IAR я бы в этом случае написал бы: __root unsigned char volatile YYY). Во-вторых: надо хотя бы внятно описать - что именно изменилось у вас за время от корректного кода до некорректного? Насколько можно понять - версия компилятора - не изменилась? Исходники - тоже? Тогда что изменилось??? Чудес не бывает. 11 часов назад, Intel4004 сказал: При оптимизации 3 и выше - код генерится правильный. А что такое "правильный" и почему думаете что он правильный? 2 часа назад, k155la3 сказал: А почему на листинге выше физ-адреса разные. Размеры bin-образа прошивки для "правильного-старого" и "неправильного-нового" как отличаются ? 1й результат ТС получил из исходника, который выше; а 2й - выдрал из рабочего проекта, в котором, вангую, больше чем 2 строки кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба 55 minutes ago, jcxz said: 1й результат ТС получил из исходника, который выше; а 2й - выдрал из рабочего проекта, в котором, вангую, больше чем 2 строки кода. могу еще добавить, возможно имеют значения типы "входных" значений для операции % в старо-рабочем и ново-тестовом проектах, возможно их неявное "приведение" к типу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Intel4004 1 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба Поясняю: достаем проект из бекапа, компиляем - видим первый пример. Дизассембляем бинарник, скомпиленый из того-же самого проекта тем же самым компилятором - видим второй пример. На адреса и прочие несоответствия внимание обращать не надо. Надо создать проект, включить оптимизацию "0 - Constant Folding" и включить галочку "don't use absolute register accesses". Добавить в проект data unsigned long XXX; data unsigned char YYY; int main (void) { XXX = 608UL; YYY = XXX % 60UL; return YYY; } Скомпилять. Посмотреть. Увидеть такое: C:0x00ED 12003F LCALL C?ULDIV(C:003F) C:0x00F0 CC XCH A,R4 C:0x00F1 CD XCH A,R5 C:0x00F2 CE XCH A,R6 C:0x00F3 CF XCH A,R7 C:0x00F4 8F0C MOV YYY(0x0C),R7 Включить оптимизацию 3 и выше. Скомпилять. Посмотреть. Увидеть такое: C:0x00E9 12003F LCALL C?ULDIV(C:003F) C:0x00EC CC XCH A,R4 C:0x00ED E8 MOV A,R0 C:0x00EE CC XCH A,R4 C:0x00EF CD XCH A,R5 C:0x00F0 E9 MOV A,R1 C:0x00F1 CD XCH A,R5 C:0x00F2 CE XCH A,R6 C:0x00F3 EA MOV A,R2 C:0x00F4 CE XCH A,R6 C:0x00F5 CF XCH A,R7 C:0x00F6 EB MOV A,R3 C:0x00F7 CF XCH A,R7 C:0x00F8 8F0C MOV YYY(0x0C),R7 Или снять галочку. Скомпилять. Посмотреть. Увидеть такое: C:0x00ED 12003F LCALL C?ULDIV(C:003F) C:0x00F0 AC00 MOV R4,0x00 C:0x00F2 AD01 MOV R5,0x01 C:0x00F4 AE02 MOV R6,0x02 C:0x00F6 AF03 MOV R7,0x03 C:0x00F8 8F0C MOV YYY(0x0C),R7 И написать мне такой-же у вас результат компиляции или нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба 57 minutes ago, Intel4004 said: Поясняю: . . . Версия компилятора чуть меньше. В настройках проекта куча других ньюансов, начиная с типа процессора, модели памяти и "всего-всея прочея". main_O0.lst main_O3.lst Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Intel4004 1 8 мая, 2022 Опубликовано 8 мая, 2022 (изменено) · Жалоба Quote COMPILER INVOKED BY: ... OPTIMIZE(3,SPEED) ... > включить оптимизацию "0 - Constant Folding" Quote В настройках проекта куча других ньюансов, начиная с типа процессора, модели памяти и "всего-всея прочея". Процессор не влияет. Я пробовал на разных адуках и ат89*. А все прочее: отличий от дефолтных настроек два - оптимизация 0 и запрет на доступ к регистрам через память. Изменено 8 мая, 2022 пользователем Intel4004 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба 7 minutes ago, Intel4004 said: > включить оптимизацию "0 - Constant Folding" там 2 листинга, первый -O0 второй -O3 Spoiler Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Intel4004 1 8 мая, 2022 Опубликовано 8 мая, 2022 (изменено) · Жалоба Да, извиняюсь, проглядел. А вас все выглядит еще интереснее и информативнее... C51 COMPILER V9.59.0.0, COMPILATION OF MODULE MMMM COMPILER INVOKED BY: C51.EXE mmmm.c OPTIMIZE(0,SPEED) BROWSE NOAREGS DEBUG OBJECTEXTEND CODE 001C 120000 E LCALL ?C?ULDIV 001F FC MOV R4,A 0020 FD MOV R5,A 0021 FE MOV R6,A 0022 FF MOV R7,A 0023 8F00 R MOV YYY,R7 У C?ULDIV на выходе результат деления в регистрах R4-R7 и остаток от деления в R0-R3. Соответственно у нас в YYY должен попасть R3. А попадает хрен знает что. Точнее тут видно, что компилятор собирался сначала перекинуть R0-R3 в R4-R7, а потом переложить из R7 в YYY, но часть команд почему-то пропала. MOV A,R0 <- это пропало MOV R4,A ... MOV A,R3 <- это пропало MOV R7,A При оптимизации 3 все еще интереснее: C51 COMPILER V9.59.0.0, COMPILATION OF MODULE MMMM COMPILER INVOKED BY: C51.EXE mmmm.c OPTIMIZE(3,SPEED) BROWSE NOAREGS DEBUG OBJECTEXTEND CODE 0018 120000 E LCALL ?C?ULDIV 001B E8 MOV A,R0 001C E9 MOV A,R1 001D EA MOV A,R2 001E EB MOV A,R3 001F F500 R MOV YYY,A MOV A,R0 MOV R4,A <- а тут пропало это ... MOV A,R3 MOV R7,A <- и это Но в результатте в YYY случайно попадает R3, который и ожидался - Вообщем все очень странно. Самое странное, что еще полгода назад тот-же самый компилятор генерил правильный код. Не нравится мне это. Сильно не нравится. Такое ощущение, что сработала закладка в компиляторе и верить ему больше нельзя... Изменено 8 мая, 2022 пользователем Intel4004 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба >> Соответственно у нас в YYY должен попасть R3. А попадает хрен знает что. Ну, изучайте "соглашение о связях (вызовах)". Хотя это "кухня" компилятора. Который для того и сделан, чтобы мы этим не заморачивались. "Прогоните" код на эмуляторе, только не на константах а на переборе делимого и делителя. Думаю, компилятор "знает что делает". ps При изменении опции компиляции по скорости, размеру, оптимизации, модели памяти итд - бинарный код вызываемой функции (и возможно соглашение о связях) скорее всего будут изменены. (под каждую оптимизацию может быть своя версия бинарной библиотеки) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Intel4004 1 8 мая, 2022 Опубликовано 8 мая, 2022 (изменено) · Жалоба 9.60 делает код который на эмуляторе гонять не надо Тут четко видно, что в результате в YYY попадает не R3, а R6. И Так-же четко видно, что пропущены несколько команд. C:0x00ED 12003F LCALL C?ULDIV(C:003F) C:0x00F0 CC XCH A,R4 C:0x00F1 CD XCH A,R5 C:0x00F2 CE XCH A,R6 C:0x00F3 CF XCH A,R7 C:0x00F4 8F0C MOV YYY(0x0C),R7 XCH A,R4 MOV A,R0 <- это пропущено XCH A,R4 <- это пропущено ... XCH A,R7 MOV A,R3 <- это пропущено XCH A,R7 <- это пропущено Я же сравниваю с результатом компиляции того-же самого проекта с теми-же самыми настройками, тем-же самым компилятором, но полгода назад. Разница видна невооруженным взглядом. Неужели вы думаете, что я из чистого интереса полез изучать код? Нет. Я внес в рабочую прошивку незначительные и не на что не влияющие изменения и она вдруг начала зависать и ребутаться по вачдогу. Полез разбираться и внезапно обнаружил, что результат оператора % теперь не соответствует действительности. А полгода назад соответствовал... Изменено 8 мая, 2022 пользователем Intel4004 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Intel4004 1 8 мая, 2022 Опубликовано 8 мая, 2022 (изменено) · Жалоба О! Нашел в бэкапах не зачищенный от результатов компиляции проект. С листингами. Скомпилял. Вот сейчас результат налицо. Сейчас строчка SEC = time%60; компиляется так (выдержка из листинга): COMPILER INVOKED BY: C51.EXE unixtime.c OMF2 OPTIMIZE(2,SPEED) BROWSE ORDER NOAREGS DEBUG CODE LISTINCLUDE SYMBOLS 32 1 SEC = time%60; ; SOURCE LINE # 32 0024 7B3C MOV R3,#03CH 0026 7A00 MOV R2,#00H 0028 7900 MOV R1,#00H 002A 7800 MOV R0,#00H 002C AF00 R MOV R7,time+03H 002E AE00 R MOV R6,time+02H 0030 AD00 R MOV R5,time+01H 0032 AC00 R MOV R4,time 0034 120000 E LCALL ?C?ULDIV 0037 CC XCH A,R4 0038 CD XCH A,R5 0039 CE XCH A,R6 003A CF XCH A,R7 003B 8FA3 MOV SEC,R7 А год назад тот-же самый проект, тем-же самым компилятором компилялся так: COMPILER INVOKED BY: C51.EXE unixtime.c OMF2 OPTIMIZE(2,SPEED) BROWSE ORDER NOAREGS DEBUG CODE LISTINCLUDE SYMBOLS 32 1 SEC = time%60; ; SOURCE LINE # 32 0024 7B3C MOV R3,#03CH 0026 7A00 MOV R2,#00H 0028 7900 MOV R1,#00H 002A 7800 MOV R0,#00H 002C AF00 R MOV R7,time+03H 002E AE00 R MOV R6,time+02H 0030 AD00 R MOV R5,time+01H 0032 AC00 R MOV R4,time 0034 120000 E LCALL ?C?ULDIV 0037 CC XCH A,R4 0038 E8 MOV A,R0 <- это исчезло 0039 CC XCH A,R4 <- это исчезло 003A CD XCH A,R5 003B E9 MOV A,R1 <- это исчезло 003C CD XCH A,R5 <- это исчезло 003D CE XCH A,R6 003E EA MOV A,R2 <- это исчезло 003F CE XCH A,R6 <- это исчезло 0040 CF XCH A,R7 0041 EB MOV A,R3 <- это исчезло 0042 CF XCH A,R7 <- это исчезло 0043 8FA3 MOV SEC,R7 Мля. Мне это не нравится. Совсем не нравится. Изменено 8 мая, 2022 пользователем Intel4004 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба 35 minutes ago, Intel4004 said: 1 . . . Неужели вы думаете, что я из чистого интереса полез изучать код? Нет. 2. Я внес в рабочую прошивку незначительные и не на что не влияющие изменения и она вдруг . . . 1. Ну, всяко бывает. Я имел ввиду, что подозревать в "ошибках" компилятор "такое-себе" занятие. Как показывает практика (моя) Он (компилятор) прав на 99.9(9). 2. Ну, изменение одного бита в мегабайтной прошивке тоже можно считать "незначительным". Значение остатка от деления может быть (делитель - 1). И как это соотносится с операндами unsigned char = UL % UL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Intel4004 1 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба Quote Ну, всяко бывает. Я имел ввиду, что подозревать в "ошибках" компилятор "такое-себе" занятие. Как показывает практика (моя) Он (компилятор) прав на 99.9(9). А я не в ошибках подрозреваю. Я сейчас практически уверен, что по каким-то условиям сработала закладка и компилятор начал преднамеренно портить код. Типа такие тихие санкции. Quote 2. Ну, изменение одного бита в мегабайтной прошивке тоже можно считать "незначительным". Посмотрите сообщение выше. Вообще никаких изменений. Ни бита. Достали из бэкапа проект и тут-же скомпиляли. И сравнили старый (годовалый) листинг с новым. Если бы этот эффект наблюдался только у меня - я бы только порадовался, что это у меня руки не из того места и это можно легко вылечить. Но ведь в ваших листингах видно то-же самое. Причем на компиляторе предыдущей версии. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 8 мая, 2022 Опубликовано 8 мая, 2022 · Жалоба Ну, теоретически - можетбыть. Софт сунулся в сеть, получил инф "стоп-лафа" и все лечение пропало. Может быть просто несовместимость с конкретной ОС. Я компилировал на Win7/32. "Исправный-старый" код-листинг на какой ОС компилировался ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться