问题
I'm trying to round an input double using a specified rounding mode in in-line assembly in C. To do so, I need to grab the FPU control word using "fstcw" and then change the bits in the word. Unfortunately I'm encountering an error on the very first line:
double roundD(double n, RoundingMode roundingMode) {
asm("fstcw %%ax \n"
::: "ax"); //clobbers
return n;
}
The assembler error I receive is:
"Error: operand type mismatch for 'fstcw'."
I'm under the impression this code snippet should store the FPU control word, which is 16 bits in length, in the AX register, which is also 16 bits in length. Just to be sure, I also tested the above code with the EAX register instead of AX, and received the same error.
What might I be missing here? Please let me know if any further information is needed.
回答1:
fstcw only works with a memory destination operand, not register.
Perhaps you're getting mixed up with fnstsw which has a separate form (separate opcode) where the destination is AX instead of specified by an addressing mode.
That was needed to efficiently branch based an an FP compare result (before fcomi to compare into EFLAGS existed), which happens more often than anything with the control word. That's why there's an AX-destination version of fnstsw
but not fnstcw
.
And BTW, you can set the rounding mode using C. #include <fenv.h>
Or far better, if SSE4.1 is available, use roundsd
(or the intrinsic) to do one rounding with a custom rounding mode, without setting / restoring the SSE rounding mode (in MXCSR, totally separate from the x87 rounding mode).
来源:https://stackoverflow.com/questions/48981197/fstcw-assembly-operand-type-mismatch