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

gcc неверно обрабатывает bool-результаты функций

Здравствуйте. Снова я со своими AVR-ками.

Пишу загрузчик в gcc (Atmel Studio 7). Отладил алгоритм в основной секции ROM при -Og оптимизации, перенёс в область загрузчика, но ужал по код по размеру: оптимизация -Os. Посыпались глюки. Стал разбираться. Возвращаемые функциями bool-результаты в ряде случаев всегда интерпретируются вызывающим кодом как true.

Копнул глубже. Функции возвращают bool-результат через регистр r24 т.к. тип bool однобайтный: объявлен как unsigned char проверил это с помощью sizeof(bool)==1.  В asm-листинге вижу как функции заносят корректное значение в r24 перед выходом, пока всё отлично.

НО в вызывающем коде проверка bool-результатов на true/false производится 2 экзотическими способами:

1) and    r24, r24

2) or    r24, r25

Второй вариант и создаёт ошибку, т.к. в r25 зачастую лежит мусор отличный от нуля. В паре мест я видел что перед вызовом функции r25 обнуляется, но обычно - нет, и кроме того через r25 в функцию передаётся аргумент.

Я изрядно позабыл avr-asm, но вроде бы логично было использовать специально-предназначенные cpi r24, 0  или  tst r24. Ладно, возможно чего-то не понимаю.

Нашёл пока лишь единственный способ побороть этот глюк - добавил ассемблерные вставки перед возвратом false. Но это лютые костыли кмк.

asm volatile ("clr r25" ::: "memory");

Может быть кто сталкивался с подобным поведением компилятора и знает более элегантные пути обхода? Допускаю, что сам мог где-то в опциях компилятора не указать какой-нибудь волшебный gcc-шный ключ.

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


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

Компилятор на 99.9% не при чём. Вы скорее всего забыли объявить ваши bool-функции в том модуле, откуда вы их вызываете. В этом случае вступает в силу неявное объявление (implicit declaration), в котором у вызываемой функции подразумевается тип int.

 

Код покажите.

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


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

@slanted спасибо, впервые узнал про преобразование типов при предупреждении "implicit declaration". По поведению точно оно: тип int в AVR 16-битный, возвращается через регистры r24:r25. И один из способов проверки int-величины на 0 может осуществляться как раз с помощью команды or r24, r25.

Ваш совет помог, но не сразу. Все инклуды были прописаны, предупреждение об implicit declaration не было, перекомпиляция не убирала ошибку. Однако после того, как выполнил Clean Solution и полностью пересобрал проект - картина изменилась. Все проверки bool-результатов выполняются посредством правильной команды

and    r24, r24 (хотя я так и не понял почему не используют tst или cpi)

Спасибо за помощь и за ликбез.

 

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


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

1 час назад, Sergey_Aleksandrovi4 сказал:

хотя я так и не понял почему не используют tst или cpi

А вы найдите десять отличий:

image.thumb.png.1f0b049d2d63a9b12208afafbfaa12e4.png

image.thumb.png.e886790a7a776d2f33937451c4710af2.png

А cpi не используется скорее всего потому, что она портит большее количество флагов.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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