Я только начинаю изучать ассемблер в своем классе информатики, и у меня есть задание округлять значение с плавающей запятой, используя указанный режим округления. Я пытался реализовать это, используя fstcw
, fldcw
и frndint
. Я изменяю контрольные биты округления, округляем число, а затем восстанавливаю предыдущие контрольные биты (требование назначения).
В настоящее время нерешенной проблемой является то, что инструкция fld %1
, похоже, загружает неправильное значение в регистр с плавающей запятой st(0)
(например, если я вызываю функцию со значением 2,6207, число -1,9427 (. ..) e-29 загружается в реестр). Это может быть связано с неправильным использованием asm()
inline *1009* или с чем-то еще, но я не уверен, почему это происходит.
Вот что у меня есть:
double roundD (double n, RoundingMode roundingMode)
{
// control word storage (2 bytes for previous, 2 for current)
char *cw = malloc(4*sizeof(char));
char *cw2 = cw + 2;
asm("fstcw %3;" // store control word in cw
"mov %3,%4;" // copy control word into cw2
"and $0xF3FF,%4;" // zero out rounding control bits
"or %2,%4;" // put new mode into rounding control bits
"fldcw %5;" // load the modified control word
"fld %1;" // load n into st(0)
"frndint;" // round n
"fstp %0;" // load st(0) back into n
"fldcw %3;" // load the old control word from cw
: "=m" (n)
: "m" (n), "m" (roundingMode),
"m" (cw), "r" (cw2), "m" (cw2) // mov requires one argument in a register
);
free(cw);
return n;
}
Буду признателен за любые указания на то, что не так с этим кодом, особенно в отношении строки fld %1
и входов / выходов asm
. (Конечно, если вы можете найти другие проблемы, не стесняйтесь, дайте мне знать о них.) Я не хочу, чтобы кто-то делал мою домашнюю работу для меня, просто укажите мне правильное направление. Спасибо!