![]() |
Objektfelder mit Inline Assembler benutzen
Moin Zusammen,
wie der Titel schon verrät, habe ich ein Objekt, dass Felder enthält, die ich mit Assembler benutzen will. Bei diesen Feldern handelt es sich um Bufferpointer. Das Auslesen des aktuellen Wertes gelingt mit
Code:
auch problemlos, nur:
mov EDI,self.FpWork
Wie bekomme ich anschliessend den veränderten Wert wieder in das Feld hinein?
Code:
habe ich dazu schon probiert, allerdings mit dem kleinen Nachteil, dass sich in FpWork nach verlassen der Routine wieder der Eingangswert befindet (in jedem der drei Fälle)
mov self.FpWork,EDI
mov [self].FpWork,EDI mov [self.FpWork],EDI Mit F7/F8 habe konnte ich schon feststellen, dass dieser Wert aber doch etwas anders sein müsste. |
Moin Zusammen,
jetzt bekomme ich allerdings Verständnisprobleme: Zu Testzwecken habe ich mir einfach mal eine kleine Testmethode gebaut, die nichts weiter macht, als einen Pointer hochzuzählen.
Code:
Hier funktioniert das Setzen des Feldes problemlos.
asm
push ESI mov ESI,self.FpTest inc ESI mov self.FpTest,ESI pop ESI end; Der Wert wird erhöht (was ja eigentlich auch so sein sollte). In der Routine, in der es nicht funktioniert, stimmt der Wert im Feld, auch noch, wenn die gesicherten Register wieder zurückgeholt werden, erst nach verlassen der Methode nicht mehr :shock: |
Auf Self sollte man in asm-Blöcken nicht direkt zugreifen. Der Zeiger Self sollte vorher in ein Register übertragen werden, über dass dann der Zugriff auf die Fehler erfolgt.
Code:
Das ist im Beispie Self in das eax Register lade hab ich aus der OnlineHilfe zum Aufruf von dynamischen und virtuellen Methoden mittels Inline Assembler.
[b]asm[/b]
push eax push edx [u]mov eax, Self[/u] mov edx, TForm1([eax]).FTest inc edx mov TForm1([eax]).FTest, edx pop edx pop eax [b]end;[/b] |
Moin jbg,
erstmal Danke für die Info. Die Hilfe welcher Delphi Version meinst Du? In der 5er kann ich nichts entsprechendes Entdecken. Die Variante self erst in ein anderes Register zu laden und dann mit diesem Wert weiter hatte ich ursprünglich auch benutzt, war dann allerdings, da es vom Ergebnis her keinen Unterschied machte wieder davon abgekommen. :? Mit ein bisschen Glück funktionierts dann ja damit stabil. |
OnlineHilfe von Delphi 6 (bei 5 steht es nicht drinnen): Assembler directives
Im Index auf "assembler statements"/"Assembler Anweisungen" gehen und dreimal den den Button ">>" drücken. (Text steht weit unten)
Code:
Ich habs gerade mit dem edi Register anstatt des eax probiert. Dabei tritt jedoch eine AV auf.
[b]asm[/b]
[i][u]// Instance pointer needs to be in EAX[/u][/i] MOV EAX, e [i]// Retrieve VMT table entry[/i] MOV EDX, [EAX] [i]// Now call the method at offset VMTOFFSET[/i] CALL DWORD PTR [EDX + VMTOFFSET TExample.VirtualMethod] [b]end[/b]; |
Moin jbg,
danke, dann ist es mir also nicht einfach entgangen. Ich hoffe mal, dass sich das Problem mit der AV bei der Verwendung von EDI nur auf das zuletzt von Dir gepostete Beispiel beschränkt. Da ich Assembler zur Beschleunigung von Stringverarbeitungen einsetzen will wäre das sonst ausgesprochen ungünstig (und irgendwie auch nicht zu erklären, denn dafür sind EDI/ESI schliesslich da) Eine in sich abgeschlossene Routine, bei der also die Felder nur gelesen, aber nicht geschrieben werden müssen tuts anstandslos. Dort verwende ich aber auch die Kombination mov EDI,self mov EDI,[EDI].FpWork usw. |
Moin jbg,
erst einmal vielen Dank für Deine Hilfe. Leider hatte auch die Art, wie es in der Hilfe beschrieben wurde keinerlei Änderung gebracht. Ich hab' die Lösung jetzt zwar gefunden, vermag aber nicht zu glauben, wie sich das Problem umgehen lässt: Als der Fehler auftrat, sah' die Routine so aus:
Code:
wenn ich es hingegen so mache, funktionierts:
[b]procedure[/b] TcsTranslator.AddToResult;
[b]asm[/b] [color=#000080]// die eigentliche Routine[/color] [b]end[/b];
Code:
Wenn ich jetzt noch das Warum wüsste...
[b]procedure[/b] TcsTranslator.AddToResult;
[b]begin[/b] [b]asm[/b] [color=#000080]// die eigentliche Routine[/color] [b]end[/b]; [b]end[/b]; |
Also, auf Anhieb würde ich als asm-Unkundiger raten, dass das erste eine reine Assembly-Funktion darstellt, während das zweite inline-Assembler in einer Object-Pascal-Funktion ist, und das Verhalten der beiden ist wohl etwas unterschiedlich... :angle2:
|
In der zweiten Variante erstellt Delphi die Aufrufe zum Sichern von Registern (Rücksprungadresse) und lädt wohl die Adresse des Self.Objektes. Zusätzlich wird am Ende die Rücksprungadresse widerhergestellt und der RETurn durchgeführt.
|
Moin OregonGhost,
ja, den Eindruck könnte man haben, nur ist es nicht entsprechend dokumentiert. Die Hilfe meint dazu: Zitat:
Im CPU Fenster hab' ich's mir allerdings noch nicht angeschaut. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:42 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz