I'm just starting to learn assembly in my computer science class, and I have an assignment to round a floating-point value using a specified rounding mode. I've tried to implement this using fstcw
, fldcw
, and frndint
. I modify the rounding control bits, round the number, and then restore the previous control bits (a requirement of the assignment).
The current outstanding problem is that the instruction fld %1
seems to load the wrong value into the st(0)
floating-point register (for example, if I call the function with a value of 2.6207, the number -1.9427(...)e-29 gets loaded into the register). This may be due to a misuse of gcc
's inline asm()
, or something else, but I'm not sure why it happens.
Here's what I have:
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;
}
I'd appreciate any pointers to what's wrong with that code, specifically relating to the fld %1
line and the asm
inputs/outputs. (Of course, if you can find other problems, feel free to let me know about them as well.) I don't want anyone to do my homework for me, just point me in the right direction. Thanks!