我刚刚开始在我的计算机科学课中学习汇编,并且我有一个使用指定的舍入模式舍入浮点值的赋值。我尝试使用fstcw
,fldcw
和frndint
来实现这一点。我修改舍入控制位,舍入数字,然后恢复先前的控制位(分配的要求)。
当前未解决的问题是指令fld %1
似乎将错误的值加载到st(0)
浮点寄存器中(例如,如果我调用值为2.6207的函数,则为-1.9427(...)e-29被加载到寄存器中)。这可能是由于误导了gcc
的内联asm()
或其他内容,但我不确定为什么会发生这种情况。
这就是我所拥有的:
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
输入/输出有关。 (当然,如果你能找到其他问题,请随时告诉我他们。)我不希望任何人为我做功课,只是指出我正确的方向。谢谢!
答案 0 :(得分:2)
这就是我所拥有的。它没有经过测试,但希望与您合作不那么粗糙。 : - )
double
roundd(double n, short mode)
{
short cw, newcw;
__asm__("fstcw %w0" : "=m" (cw));
newcw = cw & 0xf3ff | mode;
__asm__("fldcw %w0" : : "m" (newcw));
__asm__("frndint" : "+t" (n));
__asm__("fldcw %w0" : : "m" (cw));
return n;
}
尽管如果您不需要使用程序集来实现舍入模式,请考虑使用<fenv.h>
中的函数。 : - )
答案 1 :(得分:2)
当前代码至少有一个问题是它使用的是fld和fstp的单精度浮点版本。如果用fldl和fstpl替换它们,它可能会起作用。
答案 2 :(得分:0)
随着符号的变化,这意味着符号位(最重要的是第一个)不正确。 我认为指针%1错误对齐。如果你有一个字节,它可以 从0,1,2开始...但是如果你访问两个字节,地址必须是0,2,4 ......以及万一 地址的两倍必须可以通过8:0,8,16
进行分割因此,检查用于加载值的地址是否可以被8分割。汇编具有align关键字以保证数据正确对齐。