Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Frage zum Stack in Assembler (https://www.delphipraxis.net/83638-frage-zum-stack-assembler.html)

Tormentor32 5. Jan 2007 10:49


Frage zum Stack in Assembler
 
Hallo DPler!

Ich habe mir den Assembler Crashkur von [user]Balu der Bär[/user] angeschaut (sehr gutes Tutorial übrigens :thumb: ), aber bin beim rumprobieren auf ein Problem gestoßen (Ja, ich habe die Suche verwendet :wink: )

ich habe folgende Funktion:

Delphi-Quellcode:
function Addiere4(A,B,C,D: integer): integer;
asm
          ADD  EAX, B
          ADD  EAX, C
          ADD  EAX, D
end;
Da ich aber gerne mehr über den Stack wissen würde, und folgendes Gilt
Code:
EAX = A | EDX = B | ECX = C
müsste D ja auf dem Stack liegen, also sollte
Delphi-Quellcode:
function Addiere4(A,B,C,D: integer): integer;
asm
          ADD  EAX, B
          ADD  EAX, C
          POP  EDX
          ADD  EAX, EDX
end;
doch auch funktionieren oder?

Tuts aber nicht, ich kriege nur eine AV bei Adresse 0x00000000 ! Wo liegt mein Denkfehler? (ich dachte ich hätte es verstanden :cry: )

Gruß Richard

Gruber_Hans_12345 5. Jan 2007 10:58

Re: Frage zum Stack in Assembler
 
hast du dir mal im CPU Window vom Delphi angeschaut, wie deine Funktion aufgerufen wird?
Also, ob wirklich die variablen als Register übergeben werden, denn irgendwann gehen dir die registerplätze aus, und delphi muß dann die parameter per stack übergeben und nicht mehr per register.
Also einfach mal nen Breakpoint zum aufruf deiner funktion und dann das cpu fenster einblenden, da müßtest sehen, wie die parameter übergeben werden.

Tormentor32 5. Jan 2007 11:07

Re: Frage zum Stack in Assembler
 
Hmm... Was auch immer auf dem Stack liegt, es ist nicht D... ich übergebe die Zahl 4 und auf dem Stack liegt 1242668
Wie ist das denn dann mit dem Stack, komme ich, außer mit zb
Code:
ADD EAX, D
nicht anders an D?

Kedariodakon 5. Jan 2007 11:10

Re: Frage zum Stack in Assembler
 
Ich hab jetzt nicht soviel Ahnung von ASM, aber so wie es aussieht, werden die ersten 3 Zahlen per Register übergeben und die letzte Zahl auf den stack gelegt...

Am anfang der Funktion wird och eine Adresse (Welche auch immer) auf den Stack gelegt...
Dann beginnt das Rechnen... mit dem POP und holst du dir nun aber die Adresse die da hochgelegt wurde...
Schlussendlich will er sich die auf dem Stack gelegte Adresse hollen, die ja nicht mehr da ist, da du diese ja gePOPed hast :zwinker: und bekommt deine 4te Zahl...
Da springt er dann hin...

Da da aber nicht das is was sein sollte, macht er kräftig aua...


Ich hoffe das war so richtig :wink:


Bye

Robert Marquardt 5. Jan 2007 11:14

Re: Frage zum Stack in Assembler
 
POP ist immer falsch. Damit verschiebst du ja den Stackpointer und alles geht den Bach runter.

Tormentor32 5. Jan 2007 11:16

Re: Frage zum Stack in Assembler
 
Du Meinst der Holt Die Adresse, die er eigentlich braucht, um zurückzukehren vorher raus, und nimmt stattdessen meinen Wert von D als Rücksprungadresse?

Finde ich aber blöd, wäre es nicht sinnvoller, wenn er die Die Rücksprungadresse als erstes auf den Stack legt, schließlich handelt es sich ja um FIFO


Zitat:

POP ist immer falsch. Damit verschiebst du ja den Stackpointer und alles geht den Bach runter.
aber wie komme ich sonst an den Stack? Und den Wert von D (ohne das von oben zu benutzen)

edit: So muss jetzt leider weg, werde nachher nochmal reinschauen

sveni2211 5. Jan 2007 11:28

Re: Frage zum Stack in Assembler
 
Zitat:

Zitat von Tormentor32
Du Meinst der Holt Die Adresse, die er eigentlich braucht, um zurückzukehren vorher raus, und nimmt stattdessen meinen Wert von D als Rücksprungadresse?

Genau das macht er. Wenn du ASM aufrufst unterbricht das dein ganzes Programm, die Register werden auf den Stack gelegt und als letztes kommt da die Rücksprungadresse drauf. Steht die am Ende deiner Assemblerfunktion nicht wieder ganz oben auf dem Stack, dann springt das Programm irgendwo hin. EDX ist dabei eine Ausnahme. Ich glaube, das lag daran, das EDX für Sprungberechnungen gebraucht wird.

Zitat:

Zitat von Tormentor32
Finde ich aber blöd, wäre es nicht sinnvoller, wenn er die Die Rücksprungadresse als erstes auf den Stack legt, schließlich handelt es sich ja um FIFO

FIFO? FIFO wäre die serielle Schnittstelle. Der Stack ist LIFO. Der Wert, denn du zuletzt ablegst, liegt oben und wird zuerst wieder geholt. Also Last In First Out.


Zitat:

Zitat von Tormentor32
aber wie komme ich sonst an den Stack?

Werte vom Stack werden immer mit POP abgerufen und mit PUSH abgelegt.

Wenn du jetzt wüsstest, dass der Wert von D auf dem Stack genau VOR der Zieladresse steht, kämst du mit zweimal POP dran. Müsstest dann aber die Zieladresse zurückschreiben.
Also z.B.

POP EDX
POP ECX
PUSH EDX

Dann steht der Wert von vor der Rücksprungadresse auf ECX. Dann wäre aber natürlich der Wert von C weg. ;-)

Ich denke aber nicht, dass das funktioniert. Weil vor der Rücksprungadresse liegen die alten Registerwerte. Direkt vor der Rücksprungadresse müsste also EPI liegt. Du müsstest also die ganzen alten Registerwerte erstmal weg- POPen und dann zurück. Wäre also recht sinnlos, vor allem, wo du nur 4 Register hast (ohne Speicherzugriffe). Hätte dann so ein wenig was von den Türmen von Hanoi. ;-)

JasonDX 5. Jan 2007 11:33

Re: Frage zum Stack in Assembler
 
Zitat:

Zitat von sveni2211
Werte vom Stack werden immer mit PUSH abgerufen. Bedenk dann aber, dass, wenn du ein PUSH aufrufst ohne vorher POP benutzt zu haben, du die Rücksprungadresse vom Stack ziehst und die dann dort nicht mehr vorhanden ist.

Du Verwechselst Push und Pop. Zudem: Man kann den Stack wie einen ganz normalen Speicher verwenden, inklusive Random Access:
Delphi-Quellcode:
MOV EAX, [ESP + 12]
bspw.

greetz
Mike

sirius 5. Jan 2007 11:57

Re: Frage zum Stack in Assembler
 
Der Compiler von Delphi gestaltet den Funktionsaufruf recht unterschiedlich.
Dabei spielen folgende Kriterien eine Rolle
-Ist die funktion vollständiger Assembler (beginnt gleich mit asm)
-gibt es lokale Variablen (d gilt hierbei auch irgendwie als lokale Variable, da sie auf dem Stack liegt
-wie sieht die Compilerdirektive aus ('stdcall', 'pascal' ,...)

In deinem fall hast du Recht:
Die ersten 3 Variablen liegen in den "veränderbaren Registern" (eax,edx,ecx), das sind quasi die Register, bei denen es (abgesehen von Variablenübergabe) egal ist, wie sie vor bzw. nach dem Funktionsaufruf aussehen. Alle anderen Variablen landen auf dem Stack (bei 'stdcall' landen immer alle Variablen auf dem Stack)
Am besten immer im Einzelfall prüfen, was der Delphi-Compiler fabriziert.

Was passiert noch?
-also d wird auf den Stack gepusht
-->d liegt bei [esp]
-dann folgt der Funktionsaufruf mit Call (und Call legt gleich die Rücksprungadresse mit auf den Stack)
-->also liegt d jetzt bei [esp+4];
zu Beginn der Funktion (der Compiler sieht lokale Variablen (d) auf dem Stack) rettet er sich noch schnell das EBP-Register (push ebp) und setzt dir freundlicherweise diesen Base-Pointer sozusagen als Referenz
-->also liegt d jetzt bei [esp+8] bzw. bei [ebp+8]

===> übergebene Parameter liegen jetzt bei [ebp+8], [ebp+12],... lokale Variablen kannst du dir auf [ebp-4],[ebp-8],... legen. Solltest vorher aber noch den Stackpointer um die entsprechende Anzahl verschieben, falls du mal Register auf den Stack pushen willst oder aus deiner Funktion Call's tätigst.

Tormentor32 5. Jan 2007 13:20

Re: Frage zum Stack in Assembler
 
Zitat:

Zitat von sveni2211
Zitat:

Zitat von tormentor32

Finde ich aber blöd, wäre es nicht sinnvoller, wenn er die Die Rücksprungadresse als erstes auf den Stack legt, schließlich handelt es sich ja um FIFO

FIFO? FIFO wäre die serielle Schnittstelle. Der Stack ist LIFO. Der Wert, denn du zuletzt ablegst, liegt oben und wird zuerst wieder geholt. Also Last In First Out.

Die verwechsel ich immer... :oops:

Also hab ich das jetzt richtig verstanden:

Die ersten drei Parameter landen in EAX, EDX und ECX
Der Rest landet auf dem Stack, wobei Ganz oben auf dem Stack die Rücksprungadresse liegt,
erst an DRITTER (?) Stelle (also +8 ) [EDIT: DER MACHT DA JA NEN SMILIE DRAUS, WENN ICH DA KEIN LEERZEICHEN EINFÜGE]
des Stacks befindet sich der vierte Parameter der Funktion,
ich kann ihn über [ebp+8 ] ansprechen

Dieses Verhalten ist standardmäßig bei ein Funktion mit folgenden Eigenschaften

1. Es ist eine reine Assemblerfunktion
2. Sie hat mindestens 4 Parameter
3. Es gibt keine (?) lokalen variablen in der Funktion
4. Nochwas?

edit: Diese blöden Quote tags...
edit3: schon wieder diese tags...


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