سؤال

I've been trying to load a double to the FPU with FLD using GCC inline assembly.

Being not that familiar with the AT&T syntax and not having found anything on the web, I'd greatly appreciate your help. My intention was to load the address of a to EAX and then do FLD [EAX]...

double atl(double a, int adr) {
    __asm ("movl ptr %0,%%eax"::"r"(a));
    __asm ("fld qword (%eax)");
    //.... some other code here
    __asm("movl ptr %0,%%eax"::"r"(a));
    __asm("fst qword (%eax)");
    return a;
}
هل كانت مفيدة؟

المحلول

The easiest is to use the constraint "m", to load from/save to a memory location:

#include <stdio.h>
int main (void) {
    double a = 0.78539816339744;
    asm ("fldl %0;"
         "fsin;"
         "fstpl %0" : "+m"(a));
    printf("sin(45°) = %f\n", a);
    return 0;
}

The modifier "+" tells the compiler that you want your input in that memory location and to output to the same location.

GCC is allowed to reorder your lines, but it will know the semantics of that line, and it will optimize accordingly.

A more difficult example, employing loading from other variables than that are to be written to:

#include <stdio.h>
int main (void) {
    double sin_a, cos_a, a = 0.5;
    asm ("fldl %2;"
         "fsincos;"
         "fstpl %1;"
         "fstpl %0;" : "=m"(sin_a), "=m"(cos_a) : "m"(a));
    printf("sin(29°) = %f, cos(29°) = %f\n", sin_a, cos_a);
    return 0;
}

Live demo: http://ideone.com/SuvpM.

PS: I could not get GCC to load a double value, though, so I don't know if my answer is any use to you. :-(

Update:

Got it: you need to append s (for single [32 bits], as in flds, floating-point load single), l (for double [64 bits]), or t (for long double [80 bits]) explicitely. My GCC 4.6.3 assumes a single value for every memory operand …

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top