Because of the way the FPU uses registers as a stack, things are a little different when using floatingpoint values in inline assembly language coding. You must be more careful about how theFPU registers
are handled by the inline code.
You may have noticed that three different constraints dealt with the FPU register stack:
❑f references any available floating-point register
❑t references the top floating-point register
❑u references the second floating-point register
When retrieving output values from the FPU, you cannot use thef constraint; you must declare the
tor u constraints to specify the FPU register in which the output value will be, as shown in the following
example:
asm( “fsincos”
: “=t”(cosine), “=u”(sine)
: “0”(radian));
TheFSINCOS instruction places the output in the first two registers in the FPU stack. You must be sure
to specify the correct register for the correct output value. Because the input value must also be in the
ST(0)register, it uses the same register as the first output value, and is declared using the placeholder.
Thesincostest.c program demonstrates using this inline assembly code:
#include <stdio.h>
int main()
{
float angle = 90;
float radian, cosine, sine;
radian = angle / 180 * 3.14159;
asm(
"fsincos;"
:"=t"(cosine), "=u"(sine)
:"0"(radian));
printf("The cosine is %f, and the sine is %f\n", cosine, sine);
return 0;
}
The assembly language code generated by the compiler for this function looks like this:
flds -8(%ebp)
#APP
fsincos
#NO_APP
fstps -24(%ebp)
movl -24(%ebp), %eax
movl %eax, -12(%ebp)
fstps -24(%ebp)
movl -24(%ebp), %eax
movl %eax, -16(%ebp)
The radian variable is loaded into the FPU stack from the program stack using the FLDS instruction.
After the FSINCOS instruction, the two output values are popped from the FPU stack using the FSTPS
instruction and moved to their appropriate C variable location.