Autor |
Beitrag |
Allesquarks
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Do 08.02.07 15:27
virtuelle Funktionen kann man aus asm ja ungefähr so aufrufen.
Delphi-Quelltext 1: 2: 3: 4: 5:
| asm mov eax,myobject; mov eax,[eax]; call dword ptr [eax+VMTOFFSET(meineMethode)]; end; |
Wie geht deas denn nun mit Interfaces? geht das auch über die VMT oder diesmal über DMTIndex oder gar nicht?
Im disassemblat sieht es ja so aus wie ich finde. Wichtig wäre auch noch, wie ich hier (unter assembler) zwischen verschiedenen Interfaces unterscheide.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 08.02.07 23:09
Kannst Du bitte mal kurz folgenden Code compilieren und dann das Disamblat von Procedure Run geben?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| type IA = Interface Procedure A; end; IB = Interface Procedure B; end;
TTestClass = class(TObject, IA, IB) Procedure A; Procedure B; end;
var X: TTestClass;
Procedure Run; var XA: IA; XB: IB; Begin XA := X; XA.A;
XB := X; XB.B; end; |
Bitte im Disamly die Source-Zeilen mit anfügen.
P.S.: Hab leider grad kein Delphi installiert, daher die Frage nach dem Disambly. IMHO sollte es aber über CALL EAX.IA.A und CALL EAX.IB.B gehen ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Allesquarks 
      
Beiträge: 510
Win XP Prof
Delphi 7 E
|
Verfasst: Fr 09.02.07 18:10
Ich hab mal mein eigenes Testprogram genommen das ist aber fast identisch 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69:
| type myinterface1 = interface function test:integer; end;
type myinterface2 = interface function test:integer; end;
type obj1 = class(TInterfacedobject,myinterface1,myinterface2) function myinterface1.test=test1; function myinterface2.test=test2;
function test1:integer; function test2:integer; end;
type obj2 = class(TInterfacedobject,myinterface1,myinterface2) function myinterface1.test=test1; function myinterface2.test=test2;
function test1:integer; function test2:integer; end;
var Form1: TForm1;
implementation
{$R *.dfm} function obj1.test1:integer; begin result:=1; end;
function obj1.test2:integer; begin result:=2; end;
function obj2.test1:integer; begin result:=3; end;
function obj2.test2:integer; begin result:=4; end;
procedure TForm1.Button1Click(Sender: TObject); var a,b,c,d:integer;var1,var2:obj1;var3,var4:myinterface2; begin var1:=obj1.create; var2:=obj1.create; var3:=obj1.create; var4:=obj2.create;
a:=myinterface1(var1).test; b:=myinterface2(var1).test; c:=var3.test; d:=var4.test;
Edit1.text:=inttostr(a)+ inttostr(b)+ inttostr(c)+ inttostr(d); end; | Hier der CPU Auszug Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| Unit1.pas.78: a:=myinterface1(var1).test; 00454E77 8BC3 mov eax,ebx 00454E79 85C0 test eax,eax 00454E7B 7403 jz $00454e80 00454E7D 83E8F0 sub eax,<span style="color: red">-$10</span>//ich nehme mal an das ist der Offset vom Interface 00454E80 8B10 mov edx,[eax] 00454E82 FF520C call dword ptr [edx+<span style="color: red">$0c</span>]//Hier Offset der Methode 00454E85 8BF8 mov edi,eax Unit1.pas.80: b:=myinterface2(var1).test; 00454E87 8BC3 mov eax,ebx 00454E89 85C0 test eax,eax 00454E8B 7403 jz $00454e90 00454E8D 83E8F4 sub eax,<span style="color: red">-$0c</span>//Offset vom anderen Interface 00454E90 8B10 mov edx,[eax] 00454E92 FF520C call dword ptr [edx+<span style="color: red">$0c</span>]//Hier Offset der Methode 00454E95 8BD8 mov ebx,eax Unit1.pas.81: c:=var3.test; 00454E97 8B45FC mov eax,[ebp-$04] 00454E9A 8B10 mov edx,[eax] 00454E9C FF520C call dword ptr [edx+$0c] 00454E9F 8945F4 mov [ebp-$0c],eax Unit1.pas.82: d:=var4.test; 00454EA2 8B45F8 mov eax,[ebp-$08] 00454EA5 8B10 mov edx,[eax] 00454EA7 FF520C call dword ptr [edx+$0c] 00454EAA 8945F0 mov [ebp-$10],eax | Das Problem ist ja nur wie man an diese Offsets rankommt. Denn jetzt einfach immer +$0C zu schreiben ist ja ganz schön riskant wenn der Compiler sich mal entschließen sollte die Tabelle umzugruppieren dann krachts. Gleiches gilt natürlich für die Offsets wo die Interfaces stehen
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 09.02.07 21:54
Allesquarks hat folgendes geschrieben: | Ich hab mal mein eigenes Testprogram genommen das ist aber fast identisch
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69:
| type myinterface1 = interface function test:integer; end;
type myinterface2 = interface function test:integer; end;
type obj1 = class(TInterfacedobject,myinterface1,myinterface2) function myinterface1.test=test1; function myinterface2.test=test2;
function test1:integer; function test2:integer; end;
type obj2 = class(TInterfacedobject,myinterface1,myinterface2) function myinterface1.test=test1; function myinterface2.test=test2;
function test1:integer; function test2:integer; end;
var Form1: TForm1;
implementation
{$R *.dfm} function obj1.test1:integer; begin result:=1; end;
function obj1.test2:integer; begin result:=2; end;
function obj2.test1:integer; begin result:=3; end;
function obj2.test2:integer; begin result:=4; end;
procedure TForm1.Button1Click(Sender: TObject); var a,b,c,d:integer;var1,var2:obj1;var3,var4:myinterface2; begin var1:=obj1.create; var2:=obj1.create; var3:=obj1.create; var4:=obj2.create;
a:=myinterface1(var1).test; b:=myinterface2(var1).test; c:=var3.test; d:=var4.test;
Edit1.text:=inttostr(a)+ inttostr(b)+ inttostr(c)+ inttostr(d); end; | |
In deinem Source fehlte ein wichtiges Element: Klasse auf Interface konvertieren ... Hatte ich bei mir bewusst drin ... Allesquarks hat folgendes geschrieben: | Hier der CPU Auszug
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| asm mov eax,ebx test eax,eax jz $00454e80 sub eax,-$10 mov edx,[eax] call dword ptr [edx+$0c] mov edi,eax mov eax,ebx test eax,eax jz $00454e90 sub eax,-$0c mov edx,[eax] call dword ptr [edx+$0c] mov ebx,eax mov eax,[ebp-$04] mov edx,[eax] call dword ptr [edx+$0c] mov [ebp-$0c],eax mov eax,[ebp-$08] mov edx,[eax] call dword ptr [edx+$0c] mov [ebp-$10],eax end; | |
Allesquarks hat folgendes geschrieben: | Das Problem ist ja nur wie man an diese Offsets rankommt. Denn jetzt einfach immer +$0C zu schreiben ist ja ganz schön riskant wenn der Compiler sich mal entschließen sollte die Tabelle umzugruppieren dann krachts. Gleiches gilt natürlich für die Offsets wo die Interfaces stehen |
Als kleine Anmerkung: Delphi ist doof. Die drei Sterne stehen für eine Kuriosität dieses compilers: Wenn man Nil übergibt tritt die damit erzeugte Exception IMMER genau an Offset 0 auf, nicht jedoch an irgendeinem anderen Offset. So wie's aussieht, muss man dafür einiges rumpointern, wenn man's manuell machen möchte. Soweit ich das dem RTL-Source entnehmen kann, funktioniert das grob so: - Abfragen der GUID des gewünschten Interfaces. - Abfragen der Interface-Table (Gibt's an Self+vmtIntfTable, Self-72) - Suchen des gewünschten Interfaces in der Table (Man kann für diesen Schritt auch Self.QueryInterface nehmen - Aufruf der gewünschten Methode mit Delphi-Quelltext 1: 2: 3:
| asm CALL DWORD PTR [EDX] + VMTOFFSET Interfacetyp.Methodenname end; | Wobei EDX hier den Pointer auf die Interface-Tabelle beinhaltet (EAX muss dabei gerettet werden, da Self in EAX übergeben werden muss). HTH soweit...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|