Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   [Assemmbler] Aufrufkonvention erkennen (https://www.delphipraxis.net/52170-%5Bassemmbler%5D-aufrufkonvention-erkennen.html)

scp 24. Aug 2005 23:38


[Assemmbler] Aufrufkonvention erkennen
 
Kann man anhand des Aufrufs einer Funktion in einem fremden Programm, die Paramteranzahl dieser Funktion ermitteln? Ich schätze die Funktion hat etwa sieben Parameter, die ersten drei sind PWideChars, 4-8 sind einfach 0, wenn ich die Funktion zum test hooke.
Sie hat auch einen Rückgabewert, da ja eax mit 1 verglichen wird.

Eigentlich dachte ich immer, die ersten drei Paramter werden in ebx, ecx und edx abgelegt, aber wie funktioniert das nun bei so vielen Parametern?

Code:
* Reference To: KERNEL32.GetProcAddress, Ord:0197h
                                  |
:00407753 FF1580104000            Call dword ptr [00401080]
:00407759 3BC6                    cmp eax, esi
:0040775B 743D                   je 0040779A
:0040775D 56                      push esi
:0040775E FF7524                  push [ebp+24]
:00407761 FF7520                  push [ebp+20]
:00407764 FF751C                 push [ebp+1C]
:00407767 FF7518                  push [ebp+18]
:0040776A FF7514                  push [ebp+14]
:0040776D 56                      push esi
:0040776E 56                      push esi
:0040776F 56                      push esi
:00407770 56                      push esi
:00407771 56                      push esi
:00407772 FF7510                  push [ebp+10]
:00407775 FF750C                 push [ebp+0C]
:00407778 FF7508                  push [ebp+08]
:0040777B FFD0                    call eax
:0040777D 83F801                  cmp eax, 00000001
:00407780 7429                    je 004077AB
:00407782 50                      push eax
:00407783 6868254000              push 00402568
:00407788 6838254000              push 00402538

Dax 25. Aug 2005 00:16

Re: [Assemmbler] Aufrufkonvention erkennen
 
Die Parameterreihenfolge ist meinen Beobachtungen nach EAX-EDX-ECX-EBX-Top of Stack-Top of Stack-4, ... usw. Korrigiert mich, wenn ich falsch liege ;)

Wenn du den aufrufenden Code hast, musst du dann einfach nur sehen, welche Register benutzt und was auf den Stack gepusht wird, dann hast dus fast schon.

BlackJack 25. Aug 2005 00:56

Re: [Assemmbler] Aufrufkonvention erkennen
 
Zitat:

Zitat von Dax
Die Parameterreihenfolge ist meinen Beobachtungen nach EAX-EDX-ECX-EBX-Top of Stack-Top of Stack-4, ... usw. Korrigiert mich, wenn ich falsch liege ;)

das ist aber auch nur so wenn alle parameter (<(?))4 bytes gross sind und wenn es sich nicht um die Methode einer Klasse handelt, da dann in EBX der Self-Pointer gespeichert wäre.
allgemein kann man sich aber nicht darauf verlassen, wie Delphi die Parameter übergibt, da sozusagen der Compiler es selber entscheidet, wie es nun am besten ist. das gilt meines Wissens auch wenn man z.b. die Direktive "register" anhängt. (anders natürlich bei Direktiven a la "stdcall", "cdecl" etc., da bei diesen Aufrufkonventionen ja ausschliesslich der stack genutzt wird, und die direktiven zweifelsfrei angeben, wie und in welcher reihenfolge die parameter auf den stack gelegt werden müssen).

edit: das sagt die Delphi-Hilfe:
Zitat:

Zitat von Delphi-Hilfe
Die Konvention register

Bei der Konvention register werden maximal drei Parameter in den CPU-Registern übergeben, der Rest im Stack. Die Parameter werden in der Reihenfolge ihrer Deklaration übergeben (wie bei der Konvention pascal). Die ersten drei geeigneten Parameter stehen in den Registern EAX, EDX und ECX (in dieser Reihenfolge). Nur reelle, variante und strukturierte Typen sowie Methodenzeiger- und Int64-Typen sind als Registerparameter ungeeignet. Sind mehr als drei mögliche Registerparameter vorhanden, werden die ersten drei in EAX, EDX und ECX übergeben. Die restlichen Parameter werden in der Reihenfolge ihrer Deklaration im Stack abgelegt.

und ich glaube wenn man keine Konvention angibt, verwendet Delphi (wenn möglich) implizit die register-Konvention.

Robert Marquardt 25. Aug 2005 07:28

Re: [Assemmbler] Aufrufkonvention erkennen
 
Das duerfte stdcall sein. Register kann es nicht sein, da sonst Parameter in die Register geladen wuerden.
Cdecl kann es nicht sein, da sonst nach dem call die Parameter wieder vom Stack geraeumt werden wuerden.

Olli 25. Aug 2005 09:14

Re: [Assemmbler] Aufrufkonvention erkennen
 
Zitat:

Zitat von Dax
Die Parameterreihenfolge ist meinen Beobachtungen nach EAX-EDX-ECX-EBX-Top of Stack-Top of Stack-4, ... usw. Korrigiert mich, wenn ich falsch liege ;)

:shock: ... bei welcher Aufrufkonvention soll das sein? Die ist mir nicht bekannt ... Eigenkreation? :zwinker:

Zitat:

Zitat von BlackJack
allgemein kann man sich aber nicht darauf verlassen, wie Delphi die Parameter übergibt,

Erstmal sollte man wissen, daß es ein Delphi-Programm ist :mrgreen:

Zitat:

Zitat von BlackJack
da sozusagen der Compiler es selber entscheidet, wie es nun am besten ist. das gilt meines Wissens auch wenn man z.b. die Direktive "register" anhängt.

Die Reihenfolge ist ebenso bei Register und Fastcall festgelegt. Auch bei Safecall. Man muß nur wissen, mit welchem Compiler das Zielprogramm geschrieben wurde.

@scp: Wie groß ist das Programm? Kannst du es mir zuschicken?
Man kann aus diesem kleinen Abschnitt nichts sagen. Wieso? Weil zB das CALL EAX auch nur ein Parameter vom Stack nehmen könnte und ein CALL danach nochmal 3 weitere und der folgende noch weitere ... ihr seht, daß man keine Diagnose ohne Kontext stellen kann.

BlackJack 25. Aug 2005 09:54

Re: [Assemmbler] Aufrufkonvention erkennen
 
Zitat:

Zitat von Olli
Zitat:

Zitat von BlackJack
allgemein kann man sich aber nicht darauf verlassen, wie Delphi die Parameter übergibt,

Erstmal sollte man wissen, daß es ein Delphi-Programm ist :mrgreen:

oh, ich meinte das jetzt eigentlich nicht am beispiel des Debuggens wie hier, sondern eher, wenn man eigenen Code in Delphi schreibt und sich unwissentlich mit der angenommenen Parameterübergabe den Compilerotimierungen ausliefert. ;)
ich bin z.b. schon öfter derbe auf die fresse gefallen, weil ich proceduren mit parametern komplett in ASM geschrieben habe und mich dann komplett auf eine Art der Parameterübergabe festgeschrieben hatte...
(z.b. wurde von Delphi implizit die register-Konvention benutzt und ich hab in der Procedure fröhlich EAX und ECX benutzt, weil ich ja dachte, die Parameter lägen auf dem Stack)

Olli 25. Aug 2005 09:59

Re: [Assemmbler] Aufrufkonvention erkennen
 
Zitat:

Zitat von BlackJack
[...] und sich unwissentlich mit der angenommenen Parameterübergabe den Compilerotimierungen ausliefert. ;)

Kannst du mal ein Beispiel geben (zB per PM). Ist mir noch nie passiert und Robert hat mir das auch erklärt, aber ich konnte es nicht nachvollziehen.

Zitat:

Zitat von BlackJack
ich bin z.b. schon öfter derbe auf die fresse gefallen, weil ich proceduren mit parametern komplett in ASM geschrieben habe und mich dann komplett auf eine Art der Parameterübergabe festgeschrieben hatte...

asm-end statt begin-end?

Zitat:

Zitat von BlackJack
(z.b. wurde von Delphi implizit die register-Konvention benutzt und ich hab in der Procedure fröhlich EAX und ECX benutzt, weil ich ja dachte, die Parameter lägen auf dem Stack)

Aber Delphi benutzt *immer* implizit Register wenn es nicht debuggt, oder habe ich da was mißverstanden? Bei voller Optimierung ist's doch Register?!

BlackJack 25. Aug 2005 10:10

Re: [Assemmbler] Aufrufkonvention erkennen
 
Zitat:

Zitat von Olli
Zitat:

Zitat von BlackJack
[...] und sich unwissentlich mit der angenommenen Parameterübergabe den Compilerotimierungen ausliefert. ;)

Kannst du mal ein Beispiel geben (zB per PM). Ist mir noch nie passiert und Robert hat mir das auch erklärt, aber ich konnte es nicht nachvollziehen.

naja es könnte ja sein dass die Borländer in Zukunft die Ober-Aufrufkonvetion 3000 erfinden (oder in Uralt-Versionen eine andere Konvention als register benutzt haben) und ab da an genau diese standardmäßig statt der register-konvetion benutzen, und dann kann man seine proceduren, die man aufgrund der jetzigen impliziten Wahl von register daraufhin getrimmt hat ziemlich vergessen. man ist eben meiner Meinung nach Delphi total ausgeliefert, wenn man nicht explizit eine Konvention festlegt und sich aber gleichzeitig in seinem Code auf eine bestimmte Konvention einstellt.

Zitat:

Zitat von Olli
Zitat:

Zitat von BlackJack
ich bin z.b. schon öfter derbe auf die fresse gefallen, weil ich proceduren mit parametern komplett in ASM geschrieben habe und mich dann komplett auf eine Art der Parameterübergabe festgeschrieben hatte...

asm-end statt begin-end?

jo

Zitat:

Zitat von Olli
Zitat:

Zitat von BlackJack
(z.b. wurde von Delphi implizit die register-Konvention benutzt und ich hab in der Procedure fröhlich EAX und ECX benutzt, weil ich ja dachte, die Parameter lägen auf dem Stack)

Aber Delphi benutzt *immer* implizit Register wenn es nicht debuggt, oder habe ich da was mißverstanden? Bei voller Optimierung ist's doch Register?!

tja, aber das war zum meiner Anfansgzeit in Delphi, da kam ich gerade von TP rüber und war froh, verstanden zu haben, wie TP die Parameter auf den Stack legt und wie man die dann mit ASM adressieren kann. Also hab ich mir mal gedacht dass das unter Delphi genauso wäre, aber da wird ja standardmäßig register als Konvention benutzt, und ich habe mir erstmal schön die Parameter in den Registern EAX / ECX / EDX überschrieben und michgewundert warum ich im stack nur speichermüll statt meiner variablen finde :D

jbg 25. Aug 2005 10:44

Re: [Assemmbler] Aufrufkonvention erkennen
 
Zitat:

Zitat von BlackJack
Aber Delphi benutzt *immer* implizit Register wenn es nicht debuggt

Auch dort wird register als Aufrufkonvention benutzt, wenn nichts anderes erzwungen wird.

Zitat:

tja, aber das war zum meiner Anfansgzeit in Delphi, da kam ich gerade von TP rüber und war froh, verstanden zu haben, wie TP die Parameter auf den Stack legt und wie man die dann mit ASM adressieren kann.
Für sowas sollte man dann halt in die System.pas schauen. Mehr Beispiele gibt es dafür nicht :mgreen:

Zitat:

und ich habe mir erstmal schön die Parameter in den Registern EAX / ECX / EDX überschrieben
Warum so umständlich? Du kannst doch die Namen der Parameter benutzen. Wobei die ersten drei 32-Bit Parameter dann durch ihre Registernamen ersetzt werden, was wiederum zu Fehlern führen kann:
(Warnung: Fehlerhafte code)
Delphi-Quellcode:
procedure DoSomething(a, b, c: Integer);
asm
  mov eax, b
  mov edx, a
  mov ecx, c
end;
Was kommt da wohl raus?
Code:
mov eax, edx
mov edx, eax
mov ecx, ecx
ret
Und das ist Müll.

BlackJack 25. Aug 2005 10:57

Re: [Assemmbler] Aufrufkonvention erkennen
 
Zitat:

Zitat von jbg
Für sowas sollte man dann halt in die System.pas schauen. Mehr Beispiele gibt es dafür nicht :mgreen:

tja, man war jung, unerfahren, und hatte die Delphi6 PE! :mrgreen:

Zitat:

Zitat von jbg
Warum so umständlich? Du kannst doch die Namen der Parameter benutzen.

ich hab ja schon wohl die namen der Parameter benutzt, aber eben auch genau wie in deinem Beispiel dann zum rechnen schön die ganzen register benutzt. Und als blutiger TP-auf-Delphi-Umsteiger dann so einen Fehler zu finden kostet einiges an Nerven ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:50 Uhr.
Seite 1 von 2  1 2      

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