2013-09-11 4 views
3

Недавно я работаю со специальной встроенной операционной системой, работающей на архитектуре MIPS. Я мало знаю об этом. Когда я использую функцию PRINTF, увидеть некоторые странные вещи:printf не может печатать float/double правильно на экране

int a = 10; 
float b = 3.14; 
double c = 3.14; 

printf("a is %d\n", a);   // I'm sorry I forgot to type the parameters just now 
printf("b is %f\n", b);   // Error 
printf("c is %f\n", c);   // Error 

Выход:

a is 10 
b is 0.000000 

a прав, но b кажется неправильным, и c даже не могут быть напечатаны. Функция printf поступает из newlib (библиотека языка C). Будьте осторожны, поплавок/двойные числа могут быть рассчитаны правильно, правильно сохранены в памяти, и они просто не могут быть напечатаны правильно.

Возможно, что-то не так с операционной системой. Мне просто интересно, что может быть причиной. Есть ли кто-нибудь, кто раньше столкнулся с этой проблемой?

+0

Вместо того, чтобы обвинять ОС, как о показе минимальный, полный, компилируемый пример ([SSCCE] (http://sscce.org))? –

+0

Можете ли вы показать фактический код? –

+0

Возможно, передайте эти параметры функции 'printf()'? Еще лучше, [прочитайте документацию] (http://en.cppreference.com/w/c/io/fprintf). – WhozCraig

ответ

5

Для MIPS-EABI требуется 8-байтовое выравнивание стека, и ваша специальная встроенная операционная система выравнивает стек на 4-байтных границах.

Приложение, которое, как представляется, функционирует правильно до тех пор, пока символ double не будет передан как аргумент функции, является типичным симптомом этой ошибки.

Необходимо обеспечить, чтобы операционная система создавала потоки с выравниванием стека по 8 байт.

+0

Обычное соглашение о вызове MIPS «O32» требует выравнивания стека по 4 байта. – markgz

+1

@markgz В соответствии с разделом * DEFAULT C CALLING CONVENTION (O32) * [MIPS32 Краткое руководство по набору инструкций] (http://www.mips.com/media/files/MD00565-2B-MIPS32-QRC-01.01. pdf): «Стек должен быть выровнен по 8 байт». –

+1

@DKrueger - +1 это потенциально проницательно и вполне может быть ответом, однако соглашение о вызове - это всего лишь контракт между частями программного обеспечения, ни одна из которых не обязательно здесь задействована. Можете ли вы продемонстрировать, что выравнивание по 8 байт отражает * аппаратное требование * или что используемая реализация printf придерживается MIPS-EABI или соглашения о вызове O32, а также является частью системы, которая делает свою собственную нестандартную вещь с процессором MIPS ? –

3

Вы уверены, что поддержка float и double поддерживается для функций ввода/вывода, таких как printf() в вашей сборке библиотеки newlib? Может быть, ваш newlib был собран с параметрами

повреждают-newlib-IO-поплавок
повреждают-newlib-ю длиной двойной

По умолчанию это "включено".

[Редактировать]

В мире встраиваемого многих приложениях не нужен поплавок/двойные операции. Но поддержка float/double в libs требует значительного объема памяти, который часто является редким ресурсом. Поэтому обычная практика отключить поддержку float/double в stdio lib, если это не требуется. В IDE эти stdio libs без поддержки float/double обычно называются «крошечными» или «маленькими». Пожалуйста, проверьте, ссылаетесь ли вы на такую ​​«крошечную» версию вашего нового пользователя.
У меня есть сильное подозрение, что это причина ваших проблем.

+0

Да, это одна из причин, но когда я скомпилировал newlib, я не даю этих двух вариантов. Так что должны быть и другие причины. Дайте один ответ. – Shadowxiaoh

+0

@Shadowxiaoh: Не очень вероятно в этом случае, но, возможно, стоит попробовать: «errno» показывает код ошибки (errno! = 0)? – Habi

0

У меня была такая же проблема с printf ("% f", some_double) на Newlib с ARM. Решение: Объявить свой стек в

unsigned long long myStackRegion[MY_STACK_SIZE/sizeof(unsigned long long)]; 

Для MIPS, вы должны убедиться, что SizeOf (без знака долго долго) == 8.

Смежные вопросы