Einzelnen Beitrag anzeigen

Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#12

Re: non-vcl Thread innerhalb einer Klasse deklarieren

  Alt 3. Aug 2007, 10:05
@Luckie
Funktioniert auch bei mir. Früher ging das doch nicht Ich musst immer extra mit virtualalloc und virtualfree statt getmem und freemem arbeiten (z.B. bei meinem Matheparser der die Funktion auch adhoc implementiert). Naja, vielleicht war ich auch nur zu vorsichtig.

virtualprotect geht so, dass du erst mit virtualquery dir die BaseAdress und die Regionsize holst und dann mit virtualprotect dieses Segment auf Page_Execute_ReadWrite legst.


@Nogge
Das Prinzip von Luckie ist etwas verzwickt. Man könnte auch sagen unsauber,... aber schön

(ab hier für 32bit-System)
1. Unterschied zwischen Funktionszeiger und Methodenzeiger: Der Funktionszeiger besteht aus einer 32bit-Adresse die wird einfach aufgerufen , fertig. Beim Methodenzeiger liegt neben der Adresse noch ein zweiter Zeiger (self), der auf die Instanz zeigt und an die Mthode als erster (versteckter) Parameter übergeben wird. Deswegen hast du immer die Variable self zur Verfügung, damit du überhaupt auf dein Objekt zugreifen kannst. Self ist quasi der erste Übergabeparameter und steht einfach im Methodenzeiger mit drin.
Deswegen gibts TMethod.Code (der stinknormale Funktionszeiger, der einfach dahin zeigt, wo die Methode anfängt, genauso wie bei einer Funktion) und TMethod.Data der "self" beinhaltet.

2. Jetzt wirds schmutzig
Was macht diese Methode MakeProcInstance.
diese Methode schreibt einfach eine neue Funktion. Die Funktion gibts vorher noch nicht im Code und nicht in der Exe. Dazu werden 15 Byte Speicher angefordert (solang soll dei Funktion werden. Und jetzt kommt ASM, was die Methode adhoc implementiert, in dem einfach der OpCode, so wie ihn der Prozessoer will, in die 15 Bytes geschrieben wird. Darin ist halt die Variable self und der Funktionszeiger hard-gecoded enthalten. sieht dann etwa so aus:
Delphi-Quellcode:
{auf dem Stack liegt jetzt folgendes
Rücksprungadresse
Parameter 1
Parameter 2
Parameter ...
}


//zwei Konstanten deren Wert die MakeProcinstance festlegt
const self:pointer=...
      funktionszeiger:pointer=...
asm
  mov ecx,self
  pop edx //bisherige Rücksprungadresse nach edx
  push ecx //self als Parameter 0 anfügen
  push edx //Rücksprungadresse zurück auf den Stack
  mov ecx,funktionszeiger //adresse nach ecx laden
  jmp ecx //und zur Methode SPRINGEN
  //hier kein Call, ansonsten würde noch eine Rücksprungadresse auf den Stack gelegt
end;

{auf dem Stack liegt jetzt folgendes
Rücksprungadresse
Parameter 0 = self
Parameter 1
Parameter 2
Parameter ...
}
Und nur dieses self ist der Unterschied zwischen Methoden und Funktionsaufruf.
(btw: da alle Parameter auf dem Stack liegen geht eben nur stdcall)

MakeProcInstance liefert jetzt die Adresse dieser neu implementierten Funktion zurück. Und diese Funktion macht eben nix weiteres, als self (welches ja in den 15 Bytes mit enthalten ist) als Parameter vorne dran zu hängen und die eigentliche Funktion (siehe Funktionszeiger) aufzurufen.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat