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!