[C] innline Assembler -> Array
-
Hallo,
ich hoffe ich hab hier im richtigen Forum gepostet, sonst bitte verschieben.
Also, ich brauche eure Hilfe. Und zwar bin ich auf der suche danach, wie man ueber den Befehl asm in C aus einem Array die Summe bildet.
Dabei stellt sich mir die Frage, wie kann ich auf die einzelnen Elemente des Arrays zugreifen, in Assembler gibt es doch nicht die [position] -Notation von C, oder?
Wie ihr vielleicht gemerkt hab bin ich relativ neu in der Assembler-Programmierung, alles was ich bis noch hingekriegt habe ist die Addtion zweir Zahlen, wie gesagt, mir fehlt der Zugriff auf die Einzelnen Elemente.Bitte um Hilfe ...
vielen dank schon mal im Voraus!
mfg
-
Tipp: In C implementieren und schauen was dann für Assemblercode raus kommt.
Gruß
-
Wenn du z.B. in eax die Basisadresse des Arrays lädst und in ecx den Schleifenzähler, kannst du mit [eax + 4*ecx] auf einzelne 32 Bit ints in diesem Array zugreifen. Oder du zählst gleich eax bei jedem Durchlauf um 4 hoch.
-
Hier mal Code-Beispiel wie ich denken würde:
DWORD meinarray[10]; __asm { mov edx, meinarray ; ptr auf meinarray laden xor ecx, ecx ; ecx auf 0 setzen xor eax, eax ; eax auf 0 setzen _loop: add eax, dword ptr [edx+ecx*4] ; *4 weil sizeof(DWORD) = 4, "dword" ptr = das dword auf welches der ptr zeigt inc ecx ; ecx um einen erhöhen cmp ecx, 10 ; prüfen ob 10 erreicht ist jnz _loop ; wenn nein, wieder zurück zur loop mov meinevariable, eax ; ergebnis speichern }
Ich möchte für die Funktionalität diese Beispiels nicht garantieren.
Aber so ungefähr müsste es meiner Meinung nach aussehen.
-
M
schrieb:
Hier mal Code-Beispiel wie ich denken würde:
DWORD meinarray[10]; __asm { mov edx, meinarray ; ptr auf meinarray laden xor ecx, ecx ; ecx auf 0 setzen xor eax, eax ; eax auf 0 setzen _loop: add eax, dword ptr [edx+ecx*4] ; *4 weil sizeof(DWORD) = 4, "dword" ptr = das dword auf welches der ptr zeigt inc ecx ; ecx um einen erhöhen cmp ecx, 10 ; prüfen ob 10 erreicht ist jnz _loop ; wenn nein, wieder zurück zur loop mov meinevariable, eax ; ergebnis speichern }
Ich möchte für die Funktionalität diese Beispiels nicht garantieren.
Aber so ungefähr müsste es meiner Meinung nach aussehen.
mov edx, meinarray
geht nat. nicht, damit greifts du auf das erste element zu. korrekt wäre
lea edx, meinarray
(meinarray ist ja auto)
meinarray ist ja nichts weiter als esp[irgendein offset] - und weil das so ist, kannst du auf das laden auch verzichten (ausserdem sparen wir uns den (in diesem falle sowieso überflüssigen) override):DWORD meinarray[10]; __asm { mov ecx, -sizeof meinarray / sizeof DWORD xor eax, eax _loop: add eax, meinarray[ecx*sizeof DWORD + sizeof meinarray] inc ecx jnz _loop mov meinevariable, eax ; ergebnis speichern }
(bin jetzt nicht ganz sicher ob man beim inline assembler sizeof auch so anwenden darf - beim externen geht es jedenfalls)
-
Das "lea edx, meinarray" stimmt, liegt wohl daran, dass ich nie mit statischen Arrays arbeite.
Wenn du mich fragst verringert dieses ständige sizeof die Leserlichkeit... mein Vorschlag wäre:
DWORD meinarray[10]; __asm { mov ecx, -10 ; array hat 10 felder, also 10 xor eax, eax _loop: add eax, dword ptr [meinarray+40+ecx*4] ; meinarray+40 = letztes element, ecx*4 von -40 bis 0 inc ecx jnz _loop mov meinevariable, eax ; ergebnis speichern }
Naja aber jeder wie ers für richtig hält. Hauptsache es ist gleich schnell. ^^ Diese Art der Aufwärtszählung von ecx ist übrigens besser als meine.
-
DWORD meinarray[10]; __asm { mov si,meinarry //meinarray Adresse nach si mov ecx,10 //für 10 DWORDS addieren xor ebx,ebx next: lodsd //Lädt über den Index Si ein DWORD aus meinarry,dach //wird Si um 4 erhöht add ebx,eax loop next //schon alle 10 Werte mov Ergebniss,ebx }
-
hermes schrieb:
DWORD meinarray[10]; __asm { mov si,meinarry //meinarray Adresse nach si mov ecx,10 //für 10 DWORDS addieren xor ebx,ebx next: lodsd //Lädt über den Index Si ein DWORD aus meinarry,dach //wird Si um 4 erhöht add ebx,eax loop next //schon alle 10 Werte mov Ergebniss,ebx }
lodsd impliziert esi. langsamer und brauch mehr register ==> Papierkorb
M
schrieb:
Das "lea edx, meinarray" stimmt, liegt wohl daran, dass ich nie mit statischen Arrays arbeite.
Wenn du mich fragst verringert dieses ständige sizeof die Leserlichkeit... mein Vorschlag wäre:
...
Naja aber jeder wie ers für richtig hält. Hauptsache es ist gleich schnell. ^^ Diese Art der Aufwärtszählung von ecx ist übrigens besser als meine.magische konstanten mitten im code sind doof weil nicht wartbar, dann definier dir wenigstens welche unmittelbar nachdem das feld deklariert wurde. das würde ich auch tun, wenn die funktion länger wäre. wenns wirklich leserlich sein soll, nimmt man sowieso kein inline assembler - wozu gibts std::accumulate
-
lodsd impliziert esi. langsamer und brauch mehr register
Kann nicht glauben das
add eax, dword ptr [meinarray+40+ecx*4] ; meinarray+40 = letztes element, ecx*4 von -40 bis 0 inc ecx jnz _loop
schneller ist als
next: lodsd //Lädt über den Index Si ein DWORD aus meinarry,dach //wird ESi um 4 erhöht add ebx,eax loop next //schon alle 10 Werte
ist.
-
Dann glaub's halt nicht, aber der loop-Befehl allein ist saulangsam. Du kannst es ja empirisch nachweisen, dann wirst auch du überzeugt sein.
-
hermes schrieb:
Kann nicht glauben das
nicht glauben, messen.
wie bereits erwähnt, legst du dich auf eine bestimmte registerbelegung fest, das ist schon mal ungünstig. im übrigen sind load-execute befehle expliziten load und executes grundsätzlich vorzuziehen (schneller und brauchen weniger code und führen zu weniger abhängigkeiten). auf allen modernen x86 prozessoren bringt loop keinerlei geschwindigkeitsvorteil; i.allg. ist es langsamer, definitiv zumindest mit intel prozessoren. das geeignete mittel, um hier zu beschleunigen, ist sowieso loop-unrolling und vektorisierung.