问题
Hey Im trying to learn how to write assembly code in my C programs. I understand integers in assembly but floats continue to trip me up.
double asmSqrt(double x) {
double o;
__asm__ ("fld %1;"
"fsqrt;"
"fst %0;"
: "=g" (o)
: "g" (x)
);
return o;
}
As you can see Im just trying to find the square root of x. But whenever I try to compile it I get an operand type mismatch error.
I followed the same syntax used here: http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx?display=Print
PS: Im using MinGW GCC on Windows XP
回答1:
You need to explicitly specify which fld
and fst
instruction variants you want. Otherwise, the compiler doesn't know what size your operand is supposed to be. This code works for me here:
__asm__ ("fldl %1 ;"
"fsqrt ;"
"fstl %0 ;"
: "=g" (o)
: "g" (x)
);
You can use a disassembler to double-check that the right opcodes for 64-bit FLD and FST (DD/0
and DD/2
) are getting emitted.
回答2:
First, why are you doing this? The compiler can do square roots itself. You just call the proper math library function, enable optimization (so it will inline standard functions) and I'd be surprised if it doesn't do what you want. The result is platform independent (i.e. you can build for 64-bit if you want, or even a whole other architecture), easy to maintain code - much better!
If you insist on doing it the hard way, gcc can also help here (I've not actually tested this):
double asmSqrt(double x) {
__asm__ ("fsqrt" : "+t" (x));
return x;
}
The t
constraint means put the value on the top of the floating-point stack - you don't have to care how it gets there. The +
means to use the value for both input and output.
Edit: Oh, and if you do want to put things in registers yourself then you had better tell the compiler about that in the 'clobbers' section or you might overwrite something it has stored there.
回答3:
double sqrt1(double n) { __asm{ fld n fsqrt } }
call the method: double result = sqrt1((double)10) for example
回答4:
Specify memory location "=m" instead of "=g". But best is to read this manual here: http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s4
Anyway, here is the solution:
double asmSqrt(double x) {
double o;
__asm__ ("fld %1;"
"fsqrt;"
"fst %0;"
: "=m" (o)
: "g" (x)
);
return o;
}
来源:https://stackoverflow.com/questions/8736601/c-inline-assembly-operand-type-mismatch-for-fst