AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Delphi Inline Assembler Zugriff auf Privates Objekt
Thema durchsuchen
Ansicht
Themen-Optionen

Delphi Inline Assembler Zugriff auf Privates Objekt

Ein Thema von OLLI_T · begonnen am 17. Nov 2003 · letzter Beitrag vom 18. Nov 2003
Antwort Antwort
Seite 1 von 2  1 2      
OLLI_T

Registriert seit: 13. Okt 2003
Ort: Nähe Wetzlar / Hessen
143 Beiträge
 
Delphi 5 Enterprise
 
#1

Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 13:28
Hallo Gemeinde!

Folgende Methode bereitet mir leichte Bauchschmerzen:

Delphi-Quellcode:
Function TDIBSection24.GetMaskValue(X,Y:DWord):Byte;
asm // eax = Self; edx = X; ecx = Y
    push ebx
    cmp [eax].FMask, 0
    je @NoMaskValue // Keine Maske definiert
    // X-Wert anpassen und überprüfen
    mov ebx, [eax].FMaskRect.Left
    sub edx, ebx // X-Offset der Maske berücksichtigen
    js @NoMaskValue // X < 0 -> ausserhalb der Maske
    mov ebx, [eax].FMask // Zeiger auf FMask Object
    cmp edx, [ebx+$08] // ebx + $08 = FMask.FWidth
    jge @NoMaskValue // X >= Width -> ausserhalb der Maske
    add edx, [ebx+$04] // Zeiger auf Byte X, 0
    // Y-Wert überprüfen und anpassen
    mov edi, [eax].FMaskRect.Top
    sub ecx, edi // Y-Offset der Maske berücksichtigen
    js @NoMaskValue // Y < 0 -> ausserhalb der Maske
    cmp ecx, [ebx+$0C] // X >= FMask.FHeight -> ausserhalb der Maske
    jge @NoMaskValue
    jecxz @FirstRow
    imul ecx, [ebx+$08] // Y-Offset nur bei Y > 0
    add edx, ecx
  @FirstRow:
    mov eax, [edx]
    and eax, $000000FF
    jmp @EndFunc
  @NoMaskValue:
    xor eax, eax // Result = 0
  @EndFunc:
    pop ebx
End;
Ich bekomme keinen direkten Zugriff auf die privaten Variablen des Objektes FMask über den Punktoperator. Die Anweisung [eax].FMask.FWidth wird vom Compiler nicht korrekt aufgelöst. So bleibt mir nur der Umweg über mov ebx, [eax].FMask den Zeiger auf das Objekt zu ziehen und den Offset zu FWidth direkt über [ebx+$04] zu setzen. Hab auch schon diverse Casting Varianten ausprobiert; leider ohne Erfolg. Vielleicht gibt es doch eine Lösung, denn so ist der GAU vorprogrammiert, wenn ich die privaten Variablen der Klasse TDIBMask ändere.

Vielen Dank für´s mitdenken.

Gruss

OLLI
No Pain No Gain!
  Mit Zitat antworten Zitat
choose

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

Re: Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 13:49
Hallo OLLI,

probier diesen Cast:
Delphi-Quellcode:
type
  TMyClass = class
    FAttribute : Integer;
  end;

  TAnotherClass = class
  private
    FAggregate : TMyClass;
  end;

//...

  asm
    mov eax, TAnotherClass([ebx]).FAggregate.FAttribute
  end;
gruß, choose
  Mit Zitat antworten Zitat
OLLI_T

Registriert seit: 13. Okt 2003
Ort: Nähe Wetzlar / Hessen
143 Beiträge
 
Delphi 5 Enterprise
 
#3

Re: Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 14:16
Hallo Choose!

So wie ich Deinen Code interpretiere gehört Deine asm-Funktion zur Klasse TAnotherClass. Dann ist der Cast aber doch unnötig. [ebx].FAggregate liefert den Zeiger auf das Objekt FAggregate. Genauso hab ich es doch probiert und bekomme vom Compiler einen völlig falschen Offset berechnet. Oder hab ich was falsch verstanden?

Gruss

OLLI
No Pain No Gain!
  Mit Zitat antworten Zitat
OLLI_T

Registriert seit: 13. Okt 2003
Ort: Nähe Wetzlar / Hessen
143 Beiträge
 
Delphi 5 Enterprise
 
#4

Re: Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 14:18
Nachtrag!

Mir erschien diese Variante noch plausibel:

mov eax, TMyClass([ebx].FAggregate).FAttribute

Dem Compiler leider nicht
No Pain No Gain!
  Mit Zitat antworten Zitat
choose

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

Re: Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 15:43
Hallo OLLI
Zitat von OLLI_T:
So wie ich Deinen Code interpretiere gehört Deine asm-Funktion zur Klasse TAnotherClass.
Nein, in den Klassen sind keine Methoden deklariert sondern dienen lediglich der Veranschaulichung des Problems mit den Attribute. Ich habe den Code zusammenhangslos verwendet.
Leider habe ich meinen Betrag etwas zu flüchtig abgegeben, er wird zwar kompiliert, allerdings zu Code, wie man ihn warhscheinlich nicht erwartet.

Wenn ich Dich richtig Verstanden habe, möchtest Du etwas in der Form
Delphi-Quellcode:
  
asm
  //Result:= MyObject.FMyStyle.FMyFont.FMyColor
  mov eax, TMyClass([ebx]).FMyStyle.FMyFont.FMyColor
end
haben, oder?

Dieser Source lässt sich leider nicht innerhalb eines Statements derefferenzieren und würde auch vom Delphi-Compiler in mehrere Statements übersetzt werden.
Sollte es sich bei einem Attribute allerdings um einen Record handeln, lässt sich der Zugriff über ein Displacement erreichen und Delphi übersetzt es korrekt:
Delphi-Quellcode:
  TMyClass = class
    FAttribute : TPoint;
  end;
var
  myObject: TMyClass;
begin
  myObject:= TMyClass.Create;
  myObject.FAttribute.x:= 42;
  myObject.FAttribute.y:= 23;

  asm
    mov ebx, myObject
    mov ecx, TMyClass([ebx]).FAttribute.y
  end;
Ich habe den Fall mit Deinem D5-Enterprise als auch mit D7-Architect getestet. Leider gibt der Compiler im Fall eines aggregierten Objekts weder eine Warnung noch einen Fehler aus.
gruß, choose
  Mit Zitat antworten Zitat
mr2

Registriert seit: 3. Mai 2003
140 Beiträge
 
Delphi 2006 Enterprise
 
#6

Re: Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 15:59
Hallo,

ich hab' zwar nur wenig Plan von Assembler, aber ich frage mich ernsthaft:

Warum?

Private Felder sind nun mal privat und wenn ihr über Trick 17 versucht direkt darauf zuzugreifen, macht ihr damit das ganze Konzept von OOP & Kapselung zu nichte

Ihr solltet lieber darüber nachdenken ob das wirklich nötig ist und ob es nicht einen einfacherern Weg gibt.
"... we know, there are known knowns; there are things we know we know. We also know there are known unknowns; that is to say we know there are some things we don't know. But there are also unknown unknowns - the ones we don't know we don't know."
  Mit Zitat antworten Zitat
OLLI_T

Registriert seit: 13. Okt 2003
Ort: Nähe Wetzlar / Hessen
143 Beiträge
 
Delphi 5 Enterprise
 
#7

Re: Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 16:00
Hallo Choose!

Erst mal vielen Dank für Deine ausführliche Nachricht! 8)

Das mit den Record-Typen ist klar. Hab ich ja auch in meinem Code verwendet (TRect).

Ich erwarte auch gar nicht, dass der Compiler das Statement innerhalb eines Befehls dereferenzieren kann. Aber ich möchte wenn nur irgend möglich Befehle wie: [ebx+$04] vermeiden. Da sind Fehler im warsten Sinne des Wortes vorprogrammiert. Es muss doch einen Weg geben, dem Compiler begreiflich zu machen, dass im Register ebx nicht der Zeiger auf das Objekt Self sondern eben ein anderes Objekt steht.

OLLI
No Pain No Gain!
  Mit Zitat antworten Zitat
OLLI_T

Registriert seit: 13. Okt 2003
Ort: Nähe Wetzlar / Hessen
143 Beiträge
 
Delphi 5 Enterprise
 
#8

Re: Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 16:12
Hallo mr2!

Hier geht es nicht um Trick 17 sondern um Perfomance. OOP find ich geil sonst würde ich nicht für meine NONVCL Anwendungen konsequent (fast) alles in Klassen kapseln.

Die beschriebene Methode ist privat deklariert und kann von aussen nicht aufgerufen werden.

Beide Klassen sind in derselben Unit von mir deklariert.

Und ob ich nun über property WidthWord read FWidth ... oder direkt auf FWidth zugreife ist doch wohl Jacke wie Hose oder?

Gruss

OLLI
No Pain No Gain!
  Mit Zitat antworten Zitat
choose

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

Re: Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 16:24
Zitat von mr2:
Warum?
Private Felder sind nun mal privat und wenn ihr über Trick 17 versucht direkt darauf zuzugreifen, macht ihr damit das ganze Konzept von OOP & Kapselung zu nichte
Hallo mr2,
wenn ich OLLI richtig verstehe, ist das nicht das eigentliche Problem: Private Felder sind außerhalb des Scopes auch in ASM nicht sichtbar. Vielmehr scheint er einen performaten Zugriff aus einer Hilfsklasse heraus erreich zu wollen (dies hätte man in C++ mit Friends, in Java mit protected und Packages und in Delphi eben über das selbe PAS-File erreicht). Darüber hinaus sind solche "17er Tricks", die Du zu meinen scheinst, auch mit purem ObjectPascal hinzubekommen...

[Edit]Inzwischen (ich hab mal wieder zulange getippt) hat OLLI das ja bestätigt [/EDIT]

Zitat von OLLI_T:
Es muss doch einen Weg geben, dem Compiler begreiflich zu machen, dass im Register ebx nicht der Zeiger auf das Objekt Self sondern eben ein anderes Objekt steht.
Hallo OLLI,

das sollte so Funktionieren (nur mit D7 getestet):
Delphi-Quellcode:
type
  TMyClass = class
  private
    FAttribute : Integer;
  public
    constructor Create(AValue: Integer);
  end;

constructor TMyClass.Create(AValue: Integer);
begin
  inherited Create;
  FAttribute:= AValue;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  myObject: TMyClass;
  myInt: Integer;
begin
  myObject:= TMyClass.Create(42);
  try
    asm
      mov ebx, myObject
      mov eax, TMyClass([ebx]).FAttribute
    end
  finally
    myObject.Free;
  end;
end;
in eax landet, wir erwartet, 0x2a.

Vielleicht kannst Du einmal eine Zuweisung in der Delphi Language schreiben, die Du gerne 1:1 in ASM hättest?
gruß, choose
  Mit Zitat antworten Zitat
OLLI_T

Registriert seit: 13. Okt 2003
Ort: Nähe Wetzlar / Hessen
143 Beiträge
 
Delphi 5 Enterprise
 
#10

Re: Delphi Inline Assembler Zugriff auf Privates Objekt

  Alt 17. Nov 2003, 17:44
Hallo Choose!

Ich brauch nix mehr in Delphi zu schreiben, weil es mit dem einfachen Cast prima funktioniert!

Schon peinlich, dass ich darauf nicht selber gekommen bin bei meinen wilden Cast Konstrukten.

Ich danke Dir jedenfalls für Deine konstruktive Hilfe.

Zur Info hier noch kurz ein Codeausschnitt:

Delphi-Quellcode:
    mov ebx, [eax].FMask // hier übertrage ich den Zeiger auf das Objekt FMask der Klasse TDIBMask ins Register ebx
    cmp edx, TDIBMask([ebx]).FWidth // Nun ist der Zugriff auf die Variablen möglich!

  cmp edx, TDIBMask([eax].FMask).FWidth // Sowas wird durchaus compiliert aber falsch ausgewertet!!!!
Viele Grüsse

OLLI
No Pain No Gain!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:57 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz