Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Inkrementieren von Eax geht nicht (https://www.delphipraxis.net/129210-inkrementieren-von-eax-geht-nicht.html)

mr_emre_d 14. Feb 2009 17:36


Inkrementieren von Eax geht nicht
 
Ich mir eine FileExists-Funktion geschrieben, die ich auf Speed
testen wollte.

Nun, manchmal funktioniert das nicht so ganz
- und zwar genau beim Inkrementieren von eax
Ich habe leider keine Ahnung warum

Delphi-Quellcode:
function _FileExists( Filename: PChar ): Boolean; stdcall;
asm
  push eax
  call GetFileAttributes
  inc eax
end;

--

{Fehlermeldung:
Zugriffsverletzung bei Adresse 77CA631B in Modul 'ntdll.dll'. Lesen von
Adresse 0153A00C.
}
MfG

Apollonius 14. Feb 2009 17:40

Re: Problem tretet manchmal auf!
 
Sehr clever. Schau noch mal nach, was stdcall bedeutet. :mrgreen: Daneben ist dein Titel absolut göttlich. :lol:

DeddyH 14. Feb 2009 17:43

Re: Problem tretet manchmal auf!
 
[OT]
Zitat:

Nun manchmal tretet da ein Fehler auf
Ich tritt Dich gleich sonstwohin :mrgreen: [/OT]

mr_emre_d 14. Feb 2009 17:45

Re: Problem tretet manchmal auf!
 
Îch hab mich nicht entscheiden können :)

Sorry leute .. kann einmal passieren :P

EDIT: Ich bin verwirrt :(

Code:
[u][url]http://de.wikipedia.org/wiki/Aufrufkonvention[/url][/u]

Die stdcall-Aufrufkonvention ist de facto die Standard-Aufrufkonvention für die Microsoft Win32-API. Funktionsparameter werden von rechts nach links übergeben. Die Register EAX, ECX, und EDX sind [b]reserviert für die Verwendung innerhalb der Funktion[/b], werden also unter Umständen verändert. Rückgabewerte werden im EAX-Register zurückgegeben. Anders als bei cdecl bereinigt die aufgerufene Funktion den Stack, nicht die aufrufende Funktion. Wegen dieser Tatsache unterstützen stdcall-Funktionen keine variablen Argumentenlisten.
eax, ecx und edx Werte können also verwendet / verändert werden ? Ich sehe das Problem nicht.

SirThornberry 14. Feb 2009 18:56

Re: Problem tritt (:D) manchmal auf!
 
gibt deinem Beitrag bitte entsprechend den Forenregeln einen aussagekräftigen Titel :)
In deinem zweiten Satz des ersten Beitrages sind mehr Worte die dein Problem beschreiben also im Titel bei dem man eigentlich diesbezüglich kreativ sein sollte.

mr_emre_d 14. Feb 2009 19:03

Re: Inkrementieren von Eax geht nicht
 
Besser so ?:D

Können wir endlich mein Problem behandeln ?

Dax 14. Feb 2009 19:05

Re: Inkrementieren von Eax geht nicht
 
Wenn ich mich gerade richtig erinnere, enthalten EAX, EDX und ECX in dieser Reihenfolge Funktionsparameter. Wäre ja auch Verschwendung, alles auf den Stack zu legen, wenn man so schöne, leckere Register hat ;)

SirThornberry 14. Feb 2009 19:07

Re: Inkrementieren von Eax geht nicht
 
hast du denn mal in der CPU-Ansicht debuggt um zu sehen ob diese Register wirklich unberührt bleiben?

Zitat:

Die Register EAX, ECX, und EDX sind reserviert für die Verwendung innerhalb der Funktion
heißt das nciht auch das GetFileAttributes diese verwenden könnte?

mr_emre_d 14. Feb 2009 19:16

Re: Inkrementieren von Eax geht nicht
 
Der Wert von Eax ändert sich nach dem Call

Wenn die Datei nicht existiert, wird Cardinal(-1) zurückgegeben
und ich inkrementiere diesen Wert um eben False(0) zu erhalten
(ansonsten wäre der Wert>0 und somit True)

:S

PS:
Ja natürlich soll GetFileAttributes Eax verwenden

Hawkeye219 14. Feb 2009 19:18

Re: Inkrementieren von Eax geht nicht
 
Hallo,

ein Vorschlag zur Lösung deines Problems: formuliere die Funktion in "reinem" Pascal und studiere den erzeugten Assembler-Code. Du wirst deinen Fehler wahrscheinlich bald finden.

Warum möchtest du eigentlich eine Assembler-Routine schreiben? Meiner Meinung nach rechtfertigt die Gesamtlaufzeit der Routine einen derartigen Aufwand nicht.

Gruß Hawkeye

mr_emre_d 14. Feb 2009 19:20

Re: Inkrementieren von Eax geht nicht
 
Zitat:

Zitat von Hawkeye219
Warum möchtest du eigentlich eine Assembler-Routine schreiben?

Einfach - weil ich mich gerade in Assembler einarbeite :P

EDIT: Ok, ich hab mir das nochmal angeschaut und habe gemerkt, dass es nun
gar nicht geht :S Ich bin nun total verwirrt
Wenn ich mit stdcall kompiliere, liefert GetFileAttributes immer -1 zurück
ansonten funktioniert das prima

Apollonius 14. Feb 2009 20:26

Re: Inkrementieren von Eax geht nicht
 
Um das mal deutlicher zu sagen: Wenn eine Stdcall-Routine aufgerufen wird, kann im Eax-Register irgendetwas stehen. Nur bei der Aufrufkonvention Register enthält es den ersten Parameter.

Mr_G 14. Feb 2009 22:34

Re: Inkrementieren von Eax geht nicht
 
Zitat:

Zitat von Apollonius
... Nur bei der Aufrufkonvention Register enthält es den ersten Parameter.

Afaik kann man die sogar weglassen wenn man bei der Funktion (so wie mr_emre_d es ja gemacht hat) statt "begin" und "end" direkt "asm" und "end" schreibt.

himitsu 14. Feb 2009 23:20

Re: Inkrementieren von Eax geht nicht
 
Bei StdCall liegen die Parameter aber auf'm Stack und nicht in den Registern!
Und das Result auf EAX.

Laß dat StdCall weg, dann sollte es gehn, oder du nutzt den Stack.

Delphi-Quellcode:
function _FileExists( Filename: PChar ): LongBool; stdcall;
asm
  push [esp+8]
  call GetFileAttributes
  inc eax
end;

function _FileExists( Filename: PChar ): LongBool;
asm
  push eax
  call GetFileAttributes
  inc eax
end;
Zitat:

Zitat von mr_emre_d
Der Wert von Eax ändert sich nach dem Call

ja klar, denn GetFileAttributes gibt ja dennoch ein ergebnis zurück

Zitat:

Zitat von mr_emre_d
Wenn die Datei nicht existiert, wird Cardinal(-1) zurückgegeben
und ich inkrementiere diesen Wert um eben False(0) zu erhalten
(ansonsten wäre der Wert>0 und somit True)

Du weißt aber, das GetFileAttributes einen Integer liefert?
Und du mindestens die unteren 16 Byte auswerten mußt ... also statt Boolean/ByteBool muß schon mindestens WordBool verwendet werden!

mr_emre_d 15. Feb 2009 00:14

Re: Inkrementieren von Eax geht nicht
 
Zitat:

Zitat von himitsu
Bei StdCall liegen die Parameter aber auf'm Stack und nicht in den Registern!
Und das Result auf EAX.

Achja ? Wusste ich gar nicht ... Das ganze wird überall sehr ungenau beschrieben.

Zitat:

Zitat von himitsu
Zitat:

Zitat von mr_emre_d
Der Wert von Eax ändert sich nach dem Call

ja klar, denn GetFileAttributes gibt ja dennoch ein ergebnis zurück

[/quote]
Das war mir bewusst :) Das war halt nur die Antwort auf den vorherigen Beitrag.

MfG

himitsu 15. Feb 2009 09:43

Re: Inkrementieren von Eax geht nicht
 
also in meiner OH steh es eigentlich recht genau ^^

Code:
[i]OH: Aufrufkonventionen[/i]
                                                  Parameterübergabe
Direktive  Parameterreihenfolge   Bereinigung  in Registern?

register   Von links nach rechts  Routine      Ja
pascal     Von links nach rechts  Routine      Nein
cdecl      Von rechts nach links  Aufrufer     Nein
[b]stdcall[/b]    Von rechts nach links  Routine      [b]Nein[/b]
safecall   Von rechts nach links  Routine      Nein

brechi 15. Feb 2009 13:46

Re: Inkrementieren von Eax geht nicht
 
wie wärs mit:

Delphi-Quellcode:
push FileName
call GetFileAttributes
inc eax
dann ist es egal obs stdcall oder register ist.

Und wenn ich mich nicht irre, kann man auch beliebig viele Begin und Ends um den asm Block schreiben. Der Compiler sollte das gleiche draus machen, als wenn sie nicht da wären.

Mr_G 15. Feb 2009 14:50

Re: Inkrementieren von Eax geht nicht
 
Zitat:

Zitat von brechi
Und wenn ich mich nicht irre, kann man auch beliebig viele Begin und Ends um den asm Block schreiben. Der Compiler sollte das gleiche draus machen, als wenn sie nicht da wären.

Das trifft nicht ganz zu: Wenn man seine Funktion oder Prozedur mit asm beginnt führt der Compiler andere Optimierungen aus und behandelt das Ganze etwas anders. Siehe dazu die OH und hier (unter 3.2)...

Apollonius 15. Feb 2009 14:54

Re: Inkrementieren von Eax geht nicht
 
Dumm ist allerdings, dass der Compiler selbst in einer reinen Assembler-Routine meint, einen Stackframe generieren zu müssen, was extrem lästig sein kann.

Dax 15. Feb 2009 15:07

Re: Inkrementieren von Eax geht nicht
 
Wie sonst soll es vom Compiler verwaltete lokale Variablen geben? ;)

brechi 15. Feb 2009 21:38

Re: Inkrementieren von Eax geht nicht
 
mr_g

kannst du mir dann ein bsp. geben wo ein

Delphi-Quellcode:
begin
asm
end;
end;
was anderes ist als ein

Delphi-Quellcode:
asm
end;
würde mich mal interessieren

Mr_G 15. Feb 2009 22:22

Re: Inkrementieren von Eax geht nicht
 
Wie gesagt... bei einer Funktion oder Prozedur:
Delphi-Quellcode:
function Foo(Bar:Integer): Boolean;
asm
end;
Das ist nicht gleich dem:
Delphi-Quellcode:
function Foo(Bar:Integer): Boolean;
begin
  asm
  end;
end;
Die OH sagt dazu:
Zitat:

Der Compiler führt für diese Routinen [erstere ^^] verschiedene Optimierungen durch:
  • Der Compiler erstellt keinen Code zum Kopieren von Wert-Parametern in lokale Variablen. Dies betrifft alle Wert-Parameter vom Typ String und alle anderen Wert-Parameter, deren Größe nicht ein, zwei oder vier Byte beträgt. Innerhalb der Routine müssen derartige Parameter als var-Parameter behandelt werden.
  • Der Compiler weist keine Funktionsergebnis-Variable zu, und eine Referenz auf das Symbol @Result ist ein Fehler. Eine Ausnahme bilden Funktionen, die eine Referenz auf einen String, eine Variante oder ein Interface zurückliefern. Die aufrufende Routine weist diesen Typen immer einen @Result-Zeiger zu.
  • Der Compiler generiert nur Stackframes für verschachtelte Routinen, für Routinen mit lokalen Parametern oder für Routinen, die über Parameter im Stack verfügen.
  • Locals ist die Größe der lokalen Variablen, Params die Größe der Parameter. Wenn sowohl Locals als auch Params Null ist, existiert kein Eintrittscode, und der Austrittscode besteht nur aus einer RET-Anweisung.
...
Gruß Mr_G

Cyf 15. Feb 2009 22:28

Re: Inkrementieren von Eax geht nicht
 
Zitat:

Zitat von Apollonius
Dumm ist allerdings, dass der Compiler selbst in einer reinen Assembler-Routine meint, einen Stackframe generieren zu müssen, was extrem lästig sein kann.

Ich lehn mich mal aus dem Fenster und behaupte, er machts nicht in wirklich jedem Fall (aber in fast jedem), ich meine mich zu erinnern, dass ich das mal durchprobiert hatte und bei bestimmten Kombinationen der Basepointer nicht gepusht wird.
Bloß der abschließende Rücksprung wird immer generiert.


Zitat:

Zitat von Dax
Wie sonst soll es vom Compiler verwaltete lokale Variablen geben? ;)

Wer braucht die schon. :wink: Wenn ich schon eine asm-Routine einbau, dann verwalte ich auch meine Variablen und den Frame selbst.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:52 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