Inline Assembler: Wert in C-Array schreiben
-
Hallo zusammen,
ich habe einige Rechenoperationen per SSE durchgeführt. Mein Ergebnis liegt nun im ersten und dritten Block des %xmm0-Regisiters (von 0 angefangen zu zählen). Ich möchte also den Wert des ersten und des dritten Blocks in ein C-float-Array schreiben, doch das gelingt mir leider noch nicht so. So sieht der Code aus:
float a[2]; float arr[4] = {1,2,3,4}; asm( "movups (%%esi), %%xmm0;" "mulps %%xmm0, %%xmm0;" "movups %%xmm0, (%%esp);" //%%xmm0 auf Stack schieben "addl $4, %%esp;" //0. Block nicht benötigt "popl %0;" //1. Block in a[0] schreiben "addl $4, %%esp;" //2.Block nicht benötigt "popl %0;" //3. Block in a[1] schreiben --> funktioniert nicht :"=r"(*a) :"S"(arr) ); printf("a[0] == %f\na[1] == %f\n",a[0],a[1]);
Irgendwie muss ich den Pointer auf das a-Array erhöhen, damit ich nun in a[1] und nicht mehr in a[0] schreibe. Das hier funktioniert jedoch nicht:
//... "popl %0;" //1. Block in a[0] schreiben "addl $4, %%esp;" //2.Block nicht benötigt "addl $4, (%0);" //Versuch nun auf a[1] zu springen -> Segmentation Fault "popl %0;" //3. Block in a[1] schreiben --> funktioniert nicht
Weiß jemand, wie ich das machen kann?
Vielen Dank
LG, freakC++
-
freakC++ schrieb:
//... "popl %0;" //1. Block in a[0] schreiben "addl $4, %%esp;" //2.Block nicht benötigt "addl $4, (%0);" //Versuch nun auf a[1] zu springen -> Segmentation Fault "popl %0;" //3. Block in a[1] schreiben --> funktioniert nicht
Weiß jemand, wie ich das machen kann?
Lass doch die Finger vom Stack! Wenn du nicht haarklein weißt, was Du da machst und was Du da überschreibst, richtest Du unglaubliche Katastrophen an. Was Du willst, geht so:
#include <stdio.h> int main ( void ) { float a[2] = {0,0}; float arr[4] = {1,2,3,4}; asm ( "movups (%%esi), %%xmm0;" "mulps %%xmm0, %%xmm0;" "psrldq $4, %%xmm0;" "movss %%xmm0, (%%edi);" "psrldq $8, %%xmm0;" "movss %%xmm0, 4(%%edi);" : :"S"(arr), "D"(a) ); for (int i=0; i<4; ++i) printf ("arr[%i] = %2f\n",i,arr[i]); for (int i=0; i<2; ++i) printf ("a[%i] = %2f\n",i,a[i]); return 0; }
viele grüße
ralph
-
Hallo!
Ok, ich werd die Finger vom Stack lassen. Ich wollte nun deine Strategie auf mein Beispiel anwenden, doch irgendwie klappt das noch nicht so. Ich versuche einfach, das erste Arrayelement um 4 zu erhöhen:
float arr[4] = {1,2,3,4}; asm( "movl (%%esi), %%eax;" //Wert des ersten Arrayelements in %eax schreiben "addl $4, %%eax;" //Wert um 4 erhöhen "movl %%eax, (%%esi);" //Wert zurück schreiben : :"S"(arr) : );
Zwar kompiliert der Code, doch wenn ich "arr" ausgeben, ist rein gar nichts geschehen. Es wird 1 2 3 4 ausgegeben, doch ich erwarte 5 2 3 4.
Eigentlich ist das doch fast dein Code. Woran haperts denn noch?
Danke für die Hilfe
LG, freakC++
-
freakC++ schrieb:
Eigentlich ist das doch fast dein Code. Woran haperts denn noch?
Fast!
Du arbeitest mit Floats (=Single). Diese haben ein anderes Bitmuster als Integer (mach Dich mal schlau: http://de.wikipedia.org/wiki/IEEE_754#Zahlenformate_und_andere_Festlegungen_des_IEEE-754-Standards). Wenn Du auf eine Float integermäßig 4 hinzuzählst, dann hast Du einen wesentlich kleineren Wert addiert - wahrscheinlich eine winzige Nachkommazahl.
So gehts:
#include <stdio.h> int main ( void ) { int arr[4] = {1,2,3,4}; asm ( "movl (%0), %%eax;" //Wert des ersten Arrayelements in %eax schreiben "addl $4, %%eax;" //Wert um 4 erhöhen "movl %%eax, (%0);" //Wert zurück schreiben : : "g"(arr) : "%eax" ); for (int i=0; i<4; ++i) printf ("arr[%i] = %i\n",i,arr[i]); return 0; }
Ich halte es nicht für eine gute Idee, Assembler mit AT&T-Syntax und Inline-Assembler des GCC zu lernen. Du brauchst aber jedenfalls so etwas Ähnliches wie ein Tutorial. Google mal nach "GCC Inline Assembler".
viele grüße
ralph