![]() |
Diverse Fragen zum Assembler Operator call
Mahlzeit Leute!
Neues Thema, neues Glück. Hier sind so ein Paar sehr gute Leute unterwegs; das muss man nutzen. Ich möchte ganz allgemein fragen, was ich bei einem Methoden- bzw. Funktionsaufruf aus einer Assembler-Klassenmethode heraus zu beachten habe. Das die ersten beiden Übergabeparameter - sofern vorhanden - ins EDX bzw. ECX Register geladen werden müssen ist klar! 1. Ich habe das Register EAX benutzt und somit ist der Zeiger auf das Objekt Self verloren gegangen. Muss ich vor einem Methodenaufruf das Register wiederherstellen oder passiert das automatisch? 2. Wie bewerkstellige ich die Übergabe von mehr als zwei Parameter. Genau diese Problematik steht mir nämlich nun bevor. Ein konkretes Beispiel soll die Fragestellung verdeutlichen. Die Funktion Horzline soll via call aufgerufen werden:
Delphi-Quellcode:
Der Assembler Code dazu wird dann etwa so aussehen:
Procedure TDIBSection24.HorzLine(X1,X2,Y:DWord);
Delphi-Quellcode:
Vielen Dank schon mal und guten Hunger.
Var SicSelf:TDIBSection24; XStart,XEnd,YPos:DWord;
asm mov SicSelf, eax // Ist das notwendig? push ecx push edx mov eax, SicSelf // Ist das notwendig? mov edx, XStart mov ecx, XEnd // Wie definiere ich Parameter "Y"? Call HorzLine pop ecx pop ecx OLLI |
Re: Diverse Fragen zum Assembler Operator call
Hallo OLLI,
irgendwann einmal hatte ich eine verdammt gute Ausarbeitung, die nicht nur mehrere Parameter, Methoden und Datentypen wie Double zu diesem Thema, sondern ebenfalls das ShortString-Handling als Funktionsergebnis behandelte. Leider verbummelt. Habe das nur überflogen, aber vielleicht hilft es: ![]() |
Re: Diverse Fragen zum Assembler Operator call
Hallo OLLI,
das hatte ich vergessen: Zitat:
Wenn Du nun die Methode Foo aus der Methode Bar heraus aufrufst,
Delphi-Quellcode:
erwartet Foo die selben Parameter, als wenn Du die Methode als Klient aufrufst
c:= Self.Foo(a,b);
Delphi-Quellcode:
(inkl des impliziten Parameters, der Referenz auf das Objekt).
c:= AnObject.Foo(a,b);
Der Code ist in beiden Fällen identisch, allerdings könnte ein anderes Objekt gemeint sein, diese Information "steckt in EAX" und kann auch nicht vom Compiler zur Übersetzung Aufrufs generiert werden (schließlich ist ihm unbekannt, für welches Objekt Bar aufreufen wurde). Vielleicht hast Du im Debugger schon einmal die Aussage "Auf Self kann aus Optimierungsgründen nicht zugegriffen werden" gelesen? Der Compiler hat hier erkannt, das die Referenz nicht länger benötigt wird und brauchte sie vorher auch nicht auf dem Stack ablegen. Wenn Du die "Referenz auf Self" verlierst, kannst Du weitere Methoden nicht länger korrekt aufrufen. Anmerkung: Sofern die Methode (und alle aus ihr aufgerufenen) den Zustand des Exemplars nicht liest oder verändert, ist es problemlos, undefinierte Werte in EAX zu übergeben. Ich hoffe das war nicht zu wirr... :gruebel: |
Re: Diverse Fragen zum Assembler Operator call
HY Choose!
OK, also werde ich EAX brav in Ruhe lassen bzw. sichern, sofern ich noch ne weitere Klassenmethode aufrufen möchte! Das mit der Optimierung und Self wird damit auch verständlich. Dann könnte ich eigentlich ausführlich schreiben:
Delphi-Quellcode:
Das entspricht dann in Pascal:
Call [EAX].HorzLine
Delphi-Quellcode:
Das mit der Parameterübergabe ist mir allerdings trotz des guten Links noch nicht ganz geläufig. Die Daten müssen auf den Stack und gemäß der Standardaufrufkonvention register von links nach rechts. Somit muss ich mein Beispiel von eben wohl in dieser Art erweitern:
Self.HorzLine(XStart,XEnd,Y);
Delphi-Quellcode:
Werde das mal testen, ob ich damit hinkomme! Dir noch einen schönen Nachmittag.
Var SicSelf:TDIBSection24; XStart,XEnd,YPos:DWord;
asm mov SicSelf, eax // Das muss sein! push ecx push edx mov eax, SicSelf // Das muss sein! mov edx, XStart mov ecx, XEnd push Y Call HorzLine pop Y pop edx pop ecx OLLI |
Re: Diverse Fragen zum Assembler Operator call
Self sollte in EAX stehen, muß aber nicht unbedingt. Wenn zB. die aufgerufene Methode statisch ist und keinerlei Zugriffe auf Self macht und keine weiteren Methoden aufruft, dann wird Self nicht benötigt. Dies ist aber extrem selten der Fall.
In EAX in einer Methode steht also entweder das Object selber, oder aber bei Klassenmethoden der Klassentyp der Klasse. Nun, je nachdem was für eine Methode aufgerufen wird unterscheidet sich der Assembler:
Delphi-Quellcode:
Es ist also sinnvoll in Assembler sich auf statische Methoden zu beschränken, da auch DMTIndex und VMTOffset nicht in jeder Delphi Version definiert sind.type TMyObject = class procedure StaticMethod; procedure VirtualMethod; virtual; procedure DynamicMethod; dynamic; class procedure ClassDynamicMethod; dynamic; end; asm CALL TMyObject.StaticMethod MOV EDX,[EAX] CALL DWord Ptr [EDX + VMTOffset TMyObject.VirtualMethod] PUSH ESI MOV ESI,DMTIndex TMyObject.DynamicMethod CALL System.@CallDynaInst MOV ESI,DMTIndex TMyObject.ClassDynamicMethod CALL System.@CallDynaClass POP ESI end; Man sieht auch sehr schön das überschriebene Methoden "override" ein Problem darstellen können. Haben wir eine Objectdeklaration in der überschriebene Methoden vorkommen, so wissen wir nicht, ohne die Basisklassen zu kennen, ob es eine virtuelle oder dynamische Methode ist. Somit wissen wir dann auch nicht nach welcher Art & Weise wir im Assembler vorzugehen haben. Gruß Hagen PS: übrigens kann man das in der Hilfe zur Inline Assemblersyntax nachlesen :) |
Re: Diverse Fragen zum Assembler Operator call
Willst du sichergehen, und denoch schnell un effizient auf virtuelle/dynamische methoden zugreifen so gehts auch so:
Delphi-Quellcode:
Gruß hagen
var
M: procedure of object; begin M := Self.DynaMethod; asm MOV EAX,M.Data CALL M.TMethod.Code end; end; |
Re: Diverse Fragen zum Assembler Operator call
Zitat:
Zitat:
Hast Du vielleicht ein Dokument der Art, wie ich es verloren habe und OLLI weiterhelfen könnte ("Parameterübergabe und Ergebnisrückgabe in Delphi aus Sicht der Maschine")? |
Re: Diverse Fragen zum Assembler Operator call
@OLLI: ...Und wenn Du einmal "fast" die Lösung sehen willst, wie die "Referenz auf Self" automatisch geladen wird, guck Dir mal
Delphi-Quellcode:
an und verfolge, wie denn nun tatsächlich der Wert nach ECX kommt...
{ Standard window procedure }
{ In ECX = Address of method pointer } { Out EAX = Result } function StdWndProc(Window: HWND; Message, WParam: Longint; LParam: Longint): Longint; stdcall; assembler; asm //... MOV EAX,[ECX].Longint[4] CALL [ECX].Pointer ADD ESP,12 POP EAX end; Lustige Variante, die insbesondere deshalb Interessant weil seit D5 unverändert und die Adresse von WndProc des Fensterhandles "von außen" ermittelbar ist ;) |
Re: Diverse Fragen zum Assembler Operator call
Zitat:
Gruß Hagen |
Re: Diverse Fragen zum Assembler Operator call
Zitat:
Dort bin ich erst auf diese und ähnliche Verfahren aufmerksam geworden, die man auch nutzen kann, um Win32-API-CallBacks auf Methoden inkl des Zustands eines beliebigen Objekts zu "weiterzuleiten"... Noch einmal meine Frage, Hagen :cyclops:: Hast Du zum Thema "Parameterübergabe und... mit ASM", "Nette Dinge, die man mit ASM und Delphi hinbekommt", "Pitfalls using Delphi and ASM" etc. Artikel oder sonstige Beiträge, die das Thema zusammenhängend darstellen? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:52 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