Zitat:
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?
Jein!
Als standardmäßig würde ich sowieso nichts erwarten. Bsw. kann Delphi auch mal eine lokale Variable (z.B. Zählvariable) nur im Register vorhalten und gar nicht erst auf den Stack legen. Dadurch können wieder ganz andere Sachen entstehen...
Wenn was nicht klappt kann man eh mit dem Debugger dürber gehen und sich ansehen, was der Compiler so hergestellt hat. [Strg]+[Alt]+[C] während des Debuggens hilft da Wunder.
1. Gehen wir davon aus, du baust eine reine Assemblerfunktion. Da musst du dir ja deinen Speicherplatz für lokale Variablen selber organisieren (sub esp, Anzahl_bytes).
2. Du übergibst nur 32 Bit-Variablen (Pointer oder Integer) - Boolean müsste auch gehen
(so, das müssten die Bedingungen gewesen sein)
--> Dan liegen die ersten 3 Parameter in den Registern und die nächsten (verkehrtrum) im Stack
also für
function test(m,n,o,p,q,r:integer):integer;
liegt
m -->eax
n -->edx
o -->ecx
p -->[ebp+16]
q -->[ebp+12]
r -->[ebp+8]
Das liegt an der Aufrufkonvention register (die man nicht angeben muss->standard)
Und jetzt für Aufrufkonvention stdcall
function test(m,n,o,p,q,r:integer):integer;stdcall;
m -->[ebp+8]
n -->[ebp+12]
o -->[ebp+16]
p -->[ebp+20]
q -->[ebp+24]
r -->[ebp+28]
(Die Reihenfolge ist genau andersrum und nix liegt in den Registern)
Das sind auch die unter Delphi gebräuchlichsten Aufrufkonventionen.
Was macht Delphi und warum ist das so (Beispiel für register):
Delphi-Quellcode:
//Pseudocode
push p
push q
push r
mov eax,m
mov eax,n
mov eax,o
call test
//-->Sprung zu test
push ebp
mov ebp,esp
.
.
//dein Code
.
.
pop ebp
ret
(für stdcall pusht er einfach die Register von
hinten nach vorne durch vor dem Aufruf von call)
Demnach liegen auf dem Stack:
-p
-q
-r
-[Rücksprungadresse -->nächste Adresse unterhalb von call]
-ebp (gerettet, denn auch die aufrufende Funktion will nachher ihr Basis (Referenz)-Register für lokale Variablen wiederhaben)
(für stdcall liegen alle Parameter und alle andersrum im Stack)
Und das ist alles. Jetzt ist noch zu Beachten, das der stack (Stapel) auf dem Kopf liegt:
-die Adressen werden von oben nach unten kleiner
-
Es wird immer unten angefügt
Ansonsten ist ein Stack ganz normal über Pointer adressierbar, man sollte nur wissen, wo man rumschreiben darf [esp+x] (lokale Variablen) und wo man maximal lesen darf [esp-x] (Parameter und alles andere)
Ich hoffe das war alles und es war alles richtig. Angaben sind ohne Gewähr! Bitte immer selber nachprüfen!
Edit: Verdammt: 1. Fehler korrigiert
Also bei sowas verhaspel ich mich immer. Wenn hier kein Fehler mehr drinn sein sollte könnt ihr mich küssen.
Edit2: Ich hab mal deine Funktionen kurz eingetippt
Delphi-Quellcode:
function addiere4(a,b,c,d:integer):integer;
asm
add eax,edx
add eax,ecx
add eax,[ebp+8]
end;
function addiere4stdcall(a,b,c,d:integer):integer;
stdcall;
asm
mov eax,[ebp+8]
add eax,[ebp+12]
add eax,[ebp+16]
add eax,[ebp+20]
end;
Aber wie gesagt, alles nur für Integer (bzw.Pointer). Ich glaub double landet immer auf dem Stack (egal ob register) und belegt natürlich auch 8 Bytes. Es kann allerdings auch der Stack der FPU sein. Komplizierte Compiler-Welt...