Einzelnen Beitrag anzeigen

choose

Registriert seit: 2. Nov 2003
Ort: Bei Kiel, SH
729 Beiträge
 
Delphi 2006 Architect
 
#5

Re: Inline Assembler und überladene Prozeduren?

  Alt 23. Jul 2005, 14:15
Hallo himitsu,

Zitat von himitsu:
Delphi ist dafür leider nicht ausgelegt
Schade. Hast Du eine verlässliche Quelle für diese Aussage, oder ist das die Essenz aus Deinen Bemühungen?

Delphi hat in der Tat auch andere Probleme mit Adressen im Zusammenhang mit dem @-Parameter
Delphi-Quellcode:
procedure TestProc(param: string); overload;
procedure TestProc(param: Integer); overload;

type
  TStringProc = procedure(param: string);
  TIntProc = procedure(param: Integer);
wenn Du nun eine Zuweisung der Art
Delphi-Quellcode:
var
  myStringProc: TStringProc;
  myIntProc: TIntProc;
begin
  myStringProc := @TestProc;
  myIntProc := @TestProc;
  Assert( Pointer(myIntProc)=Pointer(myStringProc) );
durchführst, weist der Compiler myIntProc dieselbe Variable zu, wie es bei Deinem Call wäre: Immer die erste.
Abhilfe schafft die Zuweisung ohne Operator
Delphi-Quellcode:
myStringProc := TestProc;
myIntProc := TestProc;
Assert( Pointer(myIntProc)<>Pointer(myStringProc) );
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:
Delphi-Quellcode:
const
  STRING_PROC : TStringProc = TestProc;
  INT_PROC: TIntPRoc = TestProc;
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,
Code:
MOV    EAX, $1234
CALL   INT_PROC   ; ? FEHLER ? Nein, siehe Erklärung
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:
Code:
MOV    EAX, $1234
CALL   INT_PROC   ; = CALL [INT_PROC]
Dies ist leider ein kleiner Performancevelust, erspart Dir aber die Änderung des bestehenden überladenen Codes oder das Einführen von Wrapper-Routinen.

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:
procedure AssemberCallsIntegerVersion; assembler;
const
  TestProc_Integer: procedure(Param: Integer) = TestProc;
asm
  MOV EAX, $1234
  CALL TestProc_Integer
end;
Ich hoffe das hilft... Und würde Dich bitten, die Frage weiterhin als "offen" zu lassen. Mich würde eine direkte Variante ebenfalls interessieren
gruß, choose
  Mit Zitat antworten Zitat