Inline Assembler(VC++): Rückgabe von Objekt
-
ich brauche in einer assembler-funktion einen std::string. dazu lasse ich mir von new einen string erzeugen. der zeiger liegt dann in eax. soweit funzt alles.
am ende der asm-funktion muss ich allerdings einen std::string zurückgeben. schreibe ich die funktion um und gebe einen zeiger zurück in eax, funktioniert alles.
sobald ich allerdings ein richtiges std::string objekt zurückgeben möchte, crasht das programm. das std::string objekt beim vc++ ist 32bit groß, weshalb ich dachte, dass man einfach den std::string in ein register schreibt. das geht allerdings nicht.call get_std_string_object ; wrappt nur new ; std::string* in eax ; wollte ich einen string* zurückgeben, würde ich jetzt zurückkehren ; alles würde funktionieren mov eax, [eax] ; "zeiger dereferenzieren" ; jetzt crasht das programm
-
terraner schrieb:
das std::string objekt beim vc++ ist 32bit groß
Verzeih mir meine Skepsis, aber das halte ich für ein Gerücht. Datenzeiger, Gesamtlänge des Speichers, aktuelle Länge des Strings? Da würde ich eher mal auf mindestens 96 Bit tippen.
Ansonsten ist das keine gute Idee, was du da vorhast. Die genaue Implementation von std::string ist nunmal nicht festgelegt. Ich würde einfach nur den Zeiger zurückgeben. Ansonsten kannst du dir auch mal eine entsprechende C++ Quelle erstellen und das Assembler Listing anschauen. Empfehlen wurde ich trotzdem nicht, das Objekt by-value mittels Assembler zurückzugeben.
-
Fürs kopieren gibt es den Copyconstructor

Am besten schaust du dir mal an, wie der Compiler das macht. Aber vermutlich macht es wenig Sinn, den Teil selbst zu implementieren (denk dran, dass der Compiler hier mehr optimieren kann, durch inlinen oä)
-
groovemaster schrieb:
Verzeih mir meine Skepsis, aber das halte ich für ein Gerücht. Datenzeiger, Gesamtlänge des Speichers, aktuelle Länge des Strings? Da würde ich eher mal auf mindestens 96 Bit tippen.
pImpl denke ich mal. ich habe das mit sizeof(std::string) rausgefunden wen es interessiert.
Ansonsten ist das keine gute Idee, was du da vorhast. Die genaue Implementation von std::string ist nunmal nicht festgelegt. Ich würde einfach nur den Zeiger zurückgeben. Ansonsten kannst du dir auch mal eine entsprechende C++ Quelle erstellen und das Assembler Listing anschauen. Empfehlen wurde ich trotzdem nicht, das Objekt by-value mittels Assembler zurückzugeben.
Fürs kopieren gibt es den Copyconstructor

ach genau. dann muss ich das ganze eben mit c machen

-
der vc++ benutzt bei einer funktion folgenden formates
retVal function_name(arg1, arg2, ...)
named return value optimization, sodass die funktion für assembler-programmierer eigentlich so aussieht:
xxx function_name(retVal&, arg1, arg2, ...)
das neue problem ist jetzt, dass irgendwann der copy-ctor aufgerufen wird.
bei aufruf des copy-constructors wird this in ecx übergeben und das zurückzugebende objekt auf den stack gepusht.
Beispiel (VC++ Disassembly):
Foo a; 004113BE lea ecx,[a] 004113C1 call Foo::Foo (4110C3h) Foo b(a); 004113C6 lea eax,[a] 004113C9 push eax 004113CA lea ecx,[b] 004113CD call Foo::Foo (411181h)
-
anscheinend gibt es keine möglichkeit einen ctor aufzurufen. funktionszeiger, adressen... sind verboten.
("'Initialisierung': 'Foo *__w64 ' kann nicht in 'beliebiger_typ' konvertiert werden
Es gibt keinen Kontext, in dem diese Konvertierung möglich ist")"An __asm block can call only global C++ functions that are not overloaded. If you call an overloaded global C++ function or a C++ member function, the compiler issues an error."
da bleibt nur eins (außer hardcodieren der adresse?):
<size_t N> struct bitset { std::string* to_string_impl() const; std::string to_string() const { return *to_string_impl(); } };