R
Du versuchst Dich an Inline-Assembler des GCC. Das ist recht trickreich und eigentlich nicht für den Endprogrammierer vorgesehen. Als allererstes solltest Du Dich von der AT&T-Syntax verabschieden und mit Intel-Syntax arbeiten. Das geht mit dem GCC-Schalter -masm=intel. Hier ein funktionierendes Programm für GCC:
#include <stdio.h>
double fl = 1.234567;
double multiply ( double mul1, double mul2 )
{
double result = 0.0;
asm
(
"fld qword ptr %[mul1] \n" // ST[0] = mul1
"fmul qword ptr %[mul2] \n" // ST[0] *= mul2
"fstp qword ptr %[result] \n" // result = ST[0], ST[0] = empty
: [result] "=m" (result) // Output-Operanden
: [mul1] "m" (mul1), [mul2] "m" (mul2) // Input-Operanden
);
return result;
}
__attribute__((noinline)) double subtract ( ) // klappt nur OHNE Optimierung
{
double result = 0.0;
asm
(
"fld qword ptr [ebp+8] \n" // ST[0] = erstes Argument auf dem Stack
"fsub qword ptr [ebp+16] \n" // ST[0] -= zweites Argument auf dem Stack
"fstp qword ptr [ebp-8] \n" // result = ST[0], ST[0] = empty
);
return result;
}
int main (void)
{
printf("%f\n",fl); // 1.234567
asm
(
"fld1 \n" // ST[0] = 1.0
"fld qword ptr _fl \n" // ST[0] = fl, ST[1] = 1.0, Unterstrich beachten!
"faddp \n" // ST[0] += ST[1], ST[1] = empty
"fstp qword ptr _fl \n" // fl = ST[0], ST[0] = empty
);
printf("%f\n",fl); // 2.234567
double mul = multiply (2.0,3.0);
printf ("%f\n",mul); // 6.000000
double sub = subtract (3.78, 2.56);
printf ("%f\n",sub); // 1.220000
return 0;
}
Du musst immer die Register im Auge behalten, weil sie wandern können. Der Inhalt von ST[0] kann also zu ST[1], ST[2] usw. werden. Mit einem Debugger kannst Du diese Wanderungen schrittweise verfolgen. Normalerweise wird die FPU gepusht und gepopt, Werte werden also oben auf den Stapel gelegt und von oben wieder gelöscht. Wenn Du die Werte auf dem Stapel lässt und munter weiter pusht, ist der Stapel bald voll und Du bekommst einen Absturz.
Spiel mal mit meinem Programm und stelle dann Fragen konkret mit Codebeispiel.
HTH
viele grüße
ralph