AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Inline Assembler in Methoden

Ein Thema von cytrinox · begonnen am 21. Jun 2007 · letzter Beitrag vom 21. Jun 2007
Antwort Antwort
cytrinox

Registriert seit: 4. Sep 2006
88 Beiträge
 
#1

Inline Assembler in Methoden

  Alt 21. Jun 2007, 10:42
Hi,

Ich hatte bisher eine Assemblerroutine als ganz normale Funktion in meiner Unit.
Jetzt bin ich grad dabei das ganze bisschen hübsch zu verpacken und dabei hab ich unter anderem auch diese Routine in eine neue Klasse gesteckt.

Allerdings kam da was ganz anderes raus als wenn ich direkt die alte Funktion aufrufe.

Ich hab dann mal kurzerhand aus function foobar: TMyType; register; ein class function foobar: TMyType; register; static; gemacht, dann läuft auch die Funktion der Klasse richtig.

Kann es sein, dass mir der self Pointer vorher den Stack zerschossen hat? die static Methode hat ja nun kein self mehr.

Gibts trotzdem ne Möglichkeit inline-ASM in Methoden zu verwenden ohne die gleich static zu machen?

Vielleicht reicht ja einfach ein pop esp;
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Inline Assembler in Methoden

  Alt 21. Jun 2007, 10:49
Na klar gibts die Möglichkeit!

Am Anfang einer Methode kann so einiges passieren. Unter anderem wird self als erster Parameter übergeben.
Zeig doch mal, was du gemacht hast!

Edit: Hier mal eine Methode von mir (stdcall)
Delphi-Quellcode:
function TParserReal.in_calc:double;
//Aufruf von implemtierter Funktion
asm
  mov eax,[esp+8] //self nach eax
  push esi
  push edi
  mov edi,[eax].FKonstanten //Konstantenarray in edi
  mov esi,[eax].Fin_args //Variablenarray in esi
  lea edx,[eax].Fv0 //Pointer auf 0 nach edx
  xor ecx,ecx //ecx löschen (Fehlerzähler)
  call [eax].[Ffunc] //Aufruf von implemntierter Funktion
  pop esi
  pop edi
  mov eax,[esp+8] //self nach eax
  mov [eax].Ffehler,ecx //Fehlerzähler speichern
end;
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
cytrinox

Registriert seit: 4. Sep 2006
88 Beiträge
 
#3

Re: Inline Assembler in Methoden

  Alt 21. Jun 2007, 13:49
Delphi-Quellcode:
function
   TmpllCpuSerial.getSerial; register;
asm
  PUSH EBX
  PUSH EDI
  MOV EDI,EAX
  MOV EAX,1
  DW $A20F
  STOSD         
  MOV EAX,EBX
  STOSD
  MOV EAX,ECX
  STOSD
  MOV EAX,EDX
  STOSD
  POP EDI               
  POP EBX
end;
Die Funktion selbst ist nur als function getSerial: TCPUID; deklariert. Da kracht es dann.
Mach ich eine class function draus und diese static läuft alles wie es soll.

So ist TCPUID deklariert:
TCPUID = array[1..4] of Longint;

brauch ich da stdcall für? oder geht das auch ohne?
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#4

Re: Inline Assembler in Methoden

  Alt 21. Jun 2007, 13:59
Hallo,

bei Methoden steht in Register EAX der Self-Zeiger. Die Adresse des Rückgabewertes findest du in Register EDX.

Gruß Hawkeye
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Inline Assembler in Methoden

  Alt 21. Jun 2007, 14:19
Delphi-Quellcode:
function TForm1.getserial:TCPUID;
{in
self    --> EAX    (Das self gibts nur bei Methoden,
@TCPUID --> EDX    (sonst landet der erste Parameter gleich in EAX)
}

asm
  PUSH EBX
  PUSH EDI
  MOV EDI,EDX //aus EAX wird EDX
  MOV EAX,1
  CPUID
  STOSD
  MOV EAX,EBX
  STOSD
  MOV EAX,ECX
  STOSD
  MOV EAX,EDX
  STOSD
  POP EDI
  POP EBX
end;
Edit: Du musst nicht zwingend irgend eine Aufrufkonvention nehmen. Du musst dich nur an diese halten (was du ja auch gemacht hast, außer dass du self nicht beachtet hast).
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
cytrinox

Registriert seit: 4. Sep 2006
88 Beiträge
 
#6

Re: Inline Assembler in Methoden

  Alt 21. Jun 2007, 14:25
D'ohhhh....

okay, muss ich irgendwas beachten bzgl. Register? Darf ich bestimmte Register nicht modifizieren? (also vorher dann mit push und pop wiederhierstellen) Muss z.B. in eax immer ein Zeiger auf self sein oder kann ich das Register problemlos modifiziert lassen?


Grad noch was anderes festgestellt:

also wenn ich jetzt eax gegen edx tausche bekomme ich wieder die richtigen Rückgabewerte angezeigt. Soweit so gut.

Aber ich hab eine Funktion die true zurückgibt:

Delphi-Quellcode:
function
   TmpllCpuSerial.cpuidAvailiable; register;
asm
   PUSHFD                     {direct access to flags no possible, only via stack}
  POP EAX               {flags to EAX}
  MOV EDX,EAX         {save current flags}
  XOR EAX,ID_BIT   {not ID bit}
  PUSH EAX               {onto stack}
  POPFD                        {from stack to flags, with not ID bit}
  PUSHFD                     {back to stack}
  POP EAX               {get back to EAX}
  XOR EAX,EDX         {check if ID bit affected}
  JZ @exit            {no, CPUID not availavle}
  MOV AL,True         {Result=True}
@exit:
  end;
Da Funktioniert das mit AL. Ersetz ich AL durch DL bekomm ich ein False zurück... Also wiso ist das hier jetzt AL und NICHT DL?
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

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

Re: Inline Assembler in Methoden

  Alt 21. Jun 2007, 14:38
*von hinten aushol*

Also:
Bei der Aufrufkonvention "register" (= Delphi Standard) landen die ersten 3 Übergabeparameter in EAX, EDX, ECX, der Rest im Stack. Wenn du eine Methode hast, ist der erste Parameter immer "self", ansonsten eben nicht und in EAX steht der erste "reguläre" Übergabeparameter (wenn es ihn denn gibt), der dann bei einer Methode wie gesagt auf Position 2 (also nach EDX) geht.

In einer Funktion/Methode kannst du mit EAX, EDX und ECX machen was du willst. Alle anderen Register müssen erhalten bleiben. Umgekehrt kannst du, wenn du eine Funktion aufrufst nicht erwarten, dass EAX, EDX und ECX am Ende der Funktion mit den gleichen Werten gefüllt sind

32-Bit Rückgabewerte (Boolean, integer, smallint, byte, ...) landen immer in EAX. Fließkommawerte werden in der FPU zurückgegeben. Bei records wird als letzter Parameter ein Pointer auf das record übergeben.
Was heisst dass für dich? Den Normalfall hast du in "cpuidAvailiable". Unabhängig ob "normale" Funktion oder Methode. In EAX landet das Ergebnis.
Bei getSerial passt das Record allerdings nicht vollständig in EAX. Deswegen schafft die aufrufende Funktion etwas Platz auf dem Stack (für den record) und übergibt einen Pointer darauf als zusätzlichen Parameter. In dem Fall ist es der einzige und er landet deswegen gleich hinter self in EDX.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
cytrinox

Registriert seit: 4. Sep 2006
88 Beiträge
 
#8

Re: Inline Assembler in Methoden

  Alt 21. Jun 2007, 14:40
okay, danke für die ausführliche Erklärung
  Mit Zitat antworten Zitat
Antwort Antwort


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 05:05 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