Zugriff auf Pointer-Inhalt
-
Hallo an alle,
ich scheitere daran auf den Inhalt eines dynamischen Arrays zuzugreifen. Wenn ich unten stehende Template-Funktion (die nur Beispielcharakter hat und nur deshalb existiert, weil Sie mein Problem gut beschreibt) mit der Parameterliste ( 1, 2, 3, etc. ) Aufrufe, dann ändert mir mein Code die Adresse des arrays "t_array" auf 00000001, 00000002, etc.
Ich greife also auf die Adresse und nicht auf den Inhalt zu. Kann mir jemand helfen?
template<size_t t, class T> T* SetArray(...) { int szArray = t; static int* t_array = new int[szArray](); _asm { mov ecx, szArray // size_t in ecx mov edx, 0 // schleifen variable mov eax, 4 // first Parameter position - 4 schleife: cmp ecx, edx // vergleiche size_t mit aktl. Position je _end // gleich zum Ende, wenn equ add eax, 4 // Inc. Parameter Position mov ebx, [ebp+eax] mov DWORD PTR t_array[edx], ebx inc edx jmp schleife // zurück zur Schleife _end: }
-
Hallo FrEEzE2046,
könntest Du bitte die Funktion in C++ schreiben, so wie Du sie Dir vorstellst, was sie machen soll, und hier posten. Irgendwie kann ich nicht verstehen, was Du genau machen willst...
-
abc.w schrieb:
Hallo FrEEzE2046,
könntest Du bitte die Funktion in C++ schreiben, so wie Du sie Dir vorstellst, was sie machen soll, und hier posten. Irgendwie kann ich nicht verstehen, was Du genau machen willst...
Hallo,
danke für die Antwort. Die Funktion soll folgendes machen:
template< size_t t, class T > T* c_SetArray(T x1, T x2, T x3) { static T* Array = new T[t]; Array[0] = x1; Array[1] = x2; Array[2] = x3; return Array; } int main() { double* dbl_array; dbl_array = c_SetArray<3, double>(1.1, 2.2, 3.3); for( int i = 0; i < 3; i++ ) cout << dbl_array[i] << endl; return 0; }
Das Ganze nur in Assembler und eben dynamisch mit undefinierter Parameterliste. Ich muss eigentlich nur wissen, wie ich auf den Inhalt von dem Array Zugreife. Ich ändere immer die Adresse, was natürlich nicht gewünscht ist.
-
Ach so, Du möchtest alle Parameter, die an die Funktion übergeben werden, in ein dynamisch angelegtes Array kopieren.
Diese drei Befehle machen es ja schon im Prinzip:mov ebx, [ebp+eax] mov DWORD PTR t_array[edx], ebx inc edx
So wie Du auf den Array zugreifst scheint für mich ok zu sein, Du benutzt die Adresse t_array[edx] und speicherst dort Inhalt von EBX. Das ist ok. Damit greifst Du tatsächlich auf den Inhalt vom Array. Allerdings wird EDX mit inc edx nur um 1 inkrementiert. Und das ist nicht ok. Du musst nämlich EDX um sizeof(T) Bytes inkrementieren... Dann hast Du ein weiteres Problem, dass z.B. sizeof(double) ist 8, also muss EDX jeweils um 8 inkrementiert werden, was man irgendwie implementieren kann, aber lesen vom Stack tust Du nur 4 Bytes, eben nur so viel, wie EBX aufnehmen kann. Und so wird es mit den Grössen nie richtig stimmen, je nach dem, wie das Template parametrisiert ist... Musst Du vielleicht anders überdenken.
-
Guten Morgen,
eine Frage hätte ich dann doch noch. Wenn ich
inc edx
wird edx um 1 inkrementiert, dass ist mir schon klar. Wenn du aber sagst, dass ich edx um sizeof(T)-Byte inkrementieren muss, dann heißt das für mich auch, dass bei t_array[edx] "edx" nicht als Index verwendet wird.
Zudem habe ich vor allem das Problem, dass ich im Debugger genau sehe, dass ich leider nicht den Inhalt des Arrays, sondern dessen Speicheradresse direkt verändere.
Wie ich oben schon geschrieben habe: Nach dem Aufruf der obenstehenden Funktion liegt das Array an Position 00000001 etc. ...
noch eine Idee?
-
Vielleicht inc DWORD PTR [edx]?
-
Melan schrieb:
Vielleicht inc DWORD PTR [edx]?
Nein, leider bringt das auch nichts.
Das Problem beginnt schon bei der Ausfürung von diesem Code:
mov edx, 0 mov ebx, [ebp+8] mov DWORD PTR t_array[edx], ebx
Wenn hier edx 0 ist, so sollte das erste Elemente von t_array angesprochen werden. In ebx habe ich den ersten Parameter gespeichert.
War dieser Parameter die Zahl 5, so soll die letzte Anweisung die 5 an die erste Stelle des Arrays schreiben.Was aber passiert ist, ist dass die Adresse von t_array verworfen und durch 00000005 ersetzt wird ...
-
FrEEzE2046 schrieb:
Was aber passiert ist, ist dass die Adresse von t_array verworfen und durch 00000005 ersetzt wird ...
Ok, Du hast mich angesteckt
Ich habe mal den Code ausprobiert und es stimmt, was Du sagst. Dann habe ich ein wenig rumexperimentiert und folgendes ist dabei rausgekommen:
#include <stdio.h> template<size_t t, class T> T* c_SetArray(...) { T* pStart = new T[t](); T* pEnd = &pStart[t]; // Structure for debugging purpose to see what is on the stack struct _StackFrame { unsigned int EBP; unsigned int Address; double Param1; double Param2; double Param3; } * pStackFrame = NULL; _asm { mov pStackFrame, ebp // for debugging only mov eax, 2 // Counter for DWORDs on the stack frame, start with 2nd DWORD mov edx, pStart Start: cmp edx, pEnd // End of array reached? jge End mov ebx, [ebp + 4 * eax] // read low 4 bytes of a parameter of type "double" mov [edx], ebx // write to array inc eax mov ebx, [ebp + 4 * eax] // get high 4 bytes of a parameter of type "double" mov [edx + 4], ebx // write to array inc eax add edx, 8 // Increment pointer, sizeof(double) == 8 jmp Start End: } return pStart; } int main(int argc, char *argv[]) { double* dbl_array = NULL; dbl_array = c_SetArray<3, double>(1.0, 1.1, 1.5); for (int i = 0; i < 3; i++) { printf("%f\n", dbl_array[i]); } return 0; }
Es funktioniert nur mit "doubles" oder anderen Datentypen, die genau 8 Byte groß sind... Wenn man die Funktion für andere Datentypen parametrisieren möchte, dann ist noch einiges zu tun. Ich würde es an deiner Stelle lassen und die Idee aufgeben. Es ist einfach viel zu aufwendig und vor allem, der Compiler würde an dieser Stelle viel besseren Code generieren. Das ist ja einer der Vorteile der Template-Funktionen, dass der Compiler anhand der gewählten Datentypen den bestmöglichen Code generieren kann...
-
abc.w schrieb:
[Es funktioniert nur mit "doubles" oder anderen Datentypen, die genau 8 Byte groß sind... Wenn man die Funktion für andere Datentypen parametrisieren möchte, dann ist noch einiges zu tun. Ich würde es an deiner Stelle lassen und die Idee aufgeben. Es ist einfach viel zu aufwendig und vor allem, der Compiler würde an dieser Stelle viel besseren Code generieren. Das ist ja einer der Vorteile der Template-Funktionen, dass der Compiler anhand der gewählten Datentypen den bestmöglichen Code generieren kann...
Erstmal vielen Dank für deine Mühen.
Gut, es ließe sich für Typen wie Integer Char usw. schon realisieren, aber selbstverständlich hast du Recht, dass eine solche Funktion extrem tricky ist, da man viele Fälle bedenken muss.Ich glaube es ist aber etwas untergegangen, dass ich oben stehende Funktion nur exemplarisch für mein Problem auf arrays zu zugreifen genommen hatte. Von daher habe ich kein Problem die Idee aufzugeben
Und die Frage beantwortet hast du mir jetzt ja. Du zählst einfach die Adresse hoch und schreibst rein. Bei meinem Weg über den Index (t_array[index]) hat er mir immer die Adresse geändert.
Hast du beim experimentieren auch den Grun dafür gefunden bzw. kannst du ihn mir sagen?
-
FrEEzE2046 schrieb:
Hast du beim experimentieren auch den Grun dafür gefunden bzw. kannst du ihn mir sagen?
Ja, der Grund ist folgender: Intel-Syntax
Diese Assembler-Zeilemov DWORD PTR t_array[edx], ebx
bedeutet, "übertragen" auf C/C++ Syntax ungefähr folgendes:
*(int*)(&(((char*)&t_array)[edx])) = ebx;
D.h. die Adresse der Variable t_array wird genommen und nicht die Adresse, die in dieser Variable steht (diese Variable ist ja "zufällig" ein Pointer)...