![]() |
Inline Assembler und überladene Prozeduren?
Also, wenn man in Pascal 'ne Überladene Funktion/Prozedur aufruft, dann entscheidet ja der Compiler anhand der Parameter, welche "Version" er verwenden muß, aber in ASM geht das ja nicht und so nimmt der Compiler immer (ist jedenfalls bei mir so) die erster Funktion/Prozedure mit dem angegebenem Namen.
Nun möchte ich aber nicht zu Dieser, sondern zu 'ner Anderen. Also wie kann ich das dem Compiler begreiflich machen?
Delphi-Quellcode:
ASM
... CALL diePozedur ... End; Procedure diePozedur(x: Integer); // << und nicht dort Procedure diePozedur(X: String); // << ich will hierhin ... |
Re: Inline Assembler und überladene Prozeduren?
Hat denn wirklich keine eine Ahnung, irgendwie muß das doch gehen?
PS: ich hab zwar schon rausgefunden, dass man irgendwas in Klammer hinter dn Prozedurnamen setzen kann, aber es wird immernoch die 1. Prozedur angesprungen. z.B.
Delphi-Quellcode:
ASM
... CALL diePozedur(Integer) ... End; Procedure diePozedur(x: String); // << und nicht dort Procedure diePozedur(X: Integer); // << ich will hierhin ... |
Re: Inline Assembler und überladene Prozeduren?
Also endlich mal 'ne Antwort. (sozusagen :? )
![]() Aber vieleicht findet sich dennoch irgendeine Lösung an :| |
Re: Inline Assembler und überladene Prozeduren?
So, hat sich erledigt ... Delphi ist dafür leider nicht ausgelegt
und es gibt anscheinend wirklich keine andere und vernünftige Lösung außer die Prozeduren nicht zu überladen. Der einzige Umweg ist, dass man es dem Compiler überlasst und die Prozeduraufrufe nur per Pascal macht. Seien es direkt Prozeduraufrufe, oder indem man die Prozedue an eine Constante/Variable übergibt und dann zu den darin enthaltenen Pointern springt. Also Erledig |
Re: Inline Assembler und überladene Prozeduren?
Hallo himitsu,
Zitat:
Delphi hat in der Tat auch andere Probleme mit Adressen im Zusammenhang mit dem @-Parameter
Delphi-Quellcode:
wenn Du nun eine Zuweisung der Art
procedure TestProc(param: string); overload;
procedure TestProc(param: Integer); overload; type TStringProc = procedure(param: string); TIntProc = procedure(param: Integer);
Delphi-Quellcode:
durchführst, weist der Compiler myIntProc dieselbe Variable zu, wie es bei Deinem Call wäre: Immer die erste.
var
myStringProc: TStringProc; myIntProc: TIntProc; begin myStringProc := @TestProc; myIntProc := @TestProc; Assert( Pointer(myIntProc)=Pointer(myStringProc) ); Abhilfe schafft die Zuweisung ohne Operator
Delphi-Quellcode:
Dein Problem wird beim Einsatz mit DLLs (zB bei BPLs) mithilfe von gesonderten Exportnamen (name manging) gelöst, was im Wesentlichen einem Vergeben eines Alias entspricht. Ohne nun die Routinen zunächst in eine BPL verschieben zu müssen, könntest Du einen solchen Alias über Konstanten realisieren:
myStringProc := TestProc;
myIntProc := TestProc; Assert( Pointer(myIntProc)<>Pointer(myStringProc) );
Delphi-Quellcode:
diese Zuweisung kann auch lokal, also in Deiner Routine geschehen, in der Du die Assembleraufrufe gestalten möchtest. Problematisch an diesem Ansatz ist leider die interne Realisierung typisierten Konstanten. Sie entsprechen in Delphi einer Art "globaler Variablen". Aus diesem Grund steht INT_PROC nun nicht für eine Adresse,
const
STRING_PROC : TStringProc = TestProc; INT_PROC: TIntPRoc = TestProc;
Code:
sondern einer globalen Pointer-Variable. Sie muss dann entsprechend beim Aufruf dereferenziert werden. Glücklicherweise übernimmt der Compiler das für uns, so dass folgendes funktioniert:
MOV EAX, $1234
CALL INT_PROC ; ? FEHLER ? Nein, siehe Erklärung
Code:
Dies ist leider ein kleiner Performancevelust, erspart Dir aber die Änderung des bestehenden überladenen Codes oder das Einführen von Wrapper-Routinen.
MOV EAX, $1234
CALL INT_PROC ; = CALL [INT_PROC] Eine Assemblerroutine, die die Integervariante der überladenen Variante von TestProc aufruft könnte demnach ohne neue Symbole nach außen zu veröffentlichen oder Anforderungen an den aufzurufenen Code zu stellen (allerdings auf Kosten einer impliziten Dereferenzierung) so aussehen:
Delphi-Quellcode:
Ich hoffe das hilft... Und würde Dich bitten, die Frage weiterhin als "offen" zu lassen. Mich würde eine direkte Variante ebenfalls interessieren ;)
procedure AssemberCallsIntegerVersion; assembler;
const TestProc_Integer: procedure(Param: Integer) = TestProc; asm MOV EAX, $1234 CALL TestProc_Integer end; |
Re: Inline Assembler und überladene Prozeduren?
hallo choose,
in deinem Beitrag werden mir 2 sachen nicht ganz klar.
Delphi-Quellcode:
du meinst doch sicher das (overload bei den proceduren aber net bei der type deklaration)procedure TestProc(param: string); overload; begin end; procedure TestProc(param: Integer); overload; begin end; type TStringProc = procedure(param: string); TIntProc = procedure(param: Integer); desweiteren wüßte ich nicht was ein kleingeschriebenes call ändern soll
Delphi-Quellcode:
es ist nunmal so das in asm alle parameter nur ein dword sind
call INT_PROC ; kein fehler
call [INT_PROC] ; kein fehler CALL INT_PROC ; kein fehler CALL [INT_PROC] ; kein fehler also wenn du jetzt
Delphi-Quellcode:
machst, woher soll delphi nun wissen ob das nen pointer (nil) oder nen 0 ist wenn ich folgende funktion habe
push 0
call irgendwas
Delphi-Quellcode:
procedure bla(p: pointer); overload;
... procedure bla(i: integer); overload; ... das einzige was ich mir eventuell vorstellen kann, ist das man halt sagt welche funktion gecalled werden soll irgendwas wie
Delphi-Quellcode:
aber leider weiß ich nicht ob es sowas gibt, btw bin ich der uall@ogc der auch das ins delphi forum geschrieben hat
call bla(0)
call bla(1) |
Re: Inline Assembler und überladene Prozeduren?
Hallo brechi,
danke für den Hinweis mit dem overload und der abweichenden Groß-/Kleinschreibung. Ich habe das entsprechend korrigiert, um weiteren Missverständnissen vorzubeugen. In der Tat macht es keinen Unterschied, ob Du den Wert zunächst dereferenziert und ich wollte darauf hinweisen, dass CALL SYMBOL in diesem Fall identisch ist mit CALL [SYMBOL], was keine Selbstverständlichkeit ist... Viel mehr zeigt es deutlich, dass der Aufruf über solche Konstanten nicht identisch ist mit dem Aufruf, den der Compiler generiert: Statt "an Ort und Stelle" die Adresse zu ermitteln geschieht dies bei der Deklaration der Konstante. Allerdings: Wenn der Compiler typisierte Konstanten nicht wie globale Variable behandeln würde, machte dies keinen Unterschied... |
Re: Inline Assembler und überladene Prozeduren?
Zitat:
Es gibt allerdings andere Sprachen, wo man derartiges angeben kann. Irgendwo im DF existiert z.B. einer dieser Beiträge wo mir gesagt wurde, daß Borland's Delphi nicht damit klar kommt. Das mit dem "Alias" bei der External-Deklaration für DLL's wußte ich auch schon, aber dieses funktioniert halt nur dann, wenn man die entsprechende Funktion z.B. in eine DLL auslagert und beim einbinden nicht wieder überlagert. Innerhalb eines Programms kommt man halt nicht weit damit. Dazu kommt dann noch, daß ich zwar unter Umständen einige Funktionen in eine DLL auslagere, und die überladenen Funktionen natürlich über andere Namen exportiere, aber dann wieder mit dem originalen Namen improtiere. Im Endeffekt bleiben dann leider nur die 2 übrigen Möglichkeiten übrig: * entweder man verzichtet auf das Überladen, aber ofmals läßt es sich halt nicht vermeiden. * oder man besorgt sich per Pascal den gewünschten Prozedur-Pointer, speichert diesen in einer Konstante/Variable und springt dann diese Prozedur/Funktion über den gepeicherten wert an. wobei letzteres auch nicht immer funktioniert ... vorallem bei bestimmten Funktionen/Prozeduren und dann auch noch bei Methoden... Und das Problemchen mit den [ ] ist mir auch schon schmerzlich aufgefallen, allerdings bei Variablen. In meinem Fall wollte ich MOV EAX, &Variable haben, aber delphi machte wegen der Variable automatisch die Klammer drum MOV EAX, [&Variable] was dann 'nen netten Fehler verursachte, der mich dann 'ne ganze Weile verrückt gemacht hatte, bis ich dann durch Zufall im IM CPU-Fenster darüber gestolpert bin :wall: Es ist schon komisch, wie Delphi immer wieder versucht intelligent zu sein und dann selbstständing vieles verändert. Mit einigen "gut gemeinten" Optimierungen hab ich auch manchmal zu kämpfen, vorallem mit denen, welche sich nicht abschalten lassen -.-'' Zitat:
aber ich hab mittler Weile wenigstens einen Weg gefunden, wie man unter Umständen dennoch eine untypisierte Konstante erstellen kann, die dennoch in einem gewissen Maße typisiert ist ^^ |
Re: Inline Assembler und überladene Prozeduren?
Baue einen "Calldispatcher" rein.
Delphi-Quellcode:
Geht nicht anders, der Assembler bzw. Linker benutzt immer die erste überladene Funktion die er findet. Ist mir auch schon aufgefallen. Allerdings habe ich festgestellt das die erste Funktion die der Linker benutzt auch immer die erste Funktion ist die im Source deklariert wurde. Bei überladenen Funktionen ist es ja meistens so das sie nur als "Typ-Konviertierungs-Funktionen" agieren, sprich mehrere überladens Funktionen gleichen Typus rufen intern im Grunde immer die gleiche reale Funktion auf. D.h. sie wandeln nur die Paramater um. Exakt das nutze ich dann aus indem diese interne Arbeits-Funktion Paramater benutzt die für Assembler Aufrufe tauglich sind. Dieses Arbeits-Funktion wird selber nicht überladen, und schwups hat sich das Problem erledigt.procedure DoCallOverload(params); begin OverloadedProc1(Params); end; procedure Asmtest; asm ... blabla call DoCallOverloaded ... blabla end; Gruß Hagen |
Re: Inline Assembler und überladene Prozeduren?
Diese möglichkeit hatte ich mittler Weile verdrängt ... da nehme ich doch lieber den Umweg über eine Konstante - somit wird nebenbei auch noch der doppelte CALL-Aufruf weggelassen ^^
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:10 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