Seite 1 von 4
Assembler: Parameter
Verfasst: Sa Nov 08, 2014 1:02 pm
von Architekt
Ich bin gerade leicht am verzweifeln:
Wenn ich Zahlen auf den Stack pushe
und dann eine Funktion (also ein Label) aufrufe und dort
Code: Alles auswählen
movl 8(%ebp), %eax
movl %eax, 0(%esp)
movl 12(%ebp), %eax
movl %eax, 4(%esp)
mache, habe ich meine Parameter wieder.
pushe ich jedoch Register oder Offsets anstelle der Zahlen, dann kann ich diese nicht mit dieser Methode wiederbekommen:
Beide Parameter sind in der aufgerufenen Funktion in diesem Fall 23, sowohl 0(%esp) als auch 4(%esp), wobei 4(%esp) ja eig. 42 sein sollte.
Was kommt da durcheinander? Darf ich keine Register/Offsets Funktions übergreifend auf den Stack packen?
Nachtrag:
Nur zum besseren Verständnis, wir reden von bspw. solchen Funktionen:
Code: Alles auswählen
.globl _add
_add:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
# Begin Parameters
movl 8(%ebp), %eax
movl %eax, 0(%esp)
movl 12(%ebp), %eax
movl %eax, 4(%esp)
# End Parameters
# ...
Nachtrag 2:
Ändere ich den Zugriff auf den zweiten Parameter ab, so dass ich als Offset 20 statt 12 benutzt, klappt es (in diesem Fall):
Warum?
Edit:
Ups völlig falsches Forum.. Kann das jemand verschieben?

Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 1:45 pm
von nufan
Architekt hat geschrieben:
Code: Alles auswählen
movl 8(%ebp), %eax
movl %eax, 0(%esp)
movl 12(%ebp), %eax
movl %eax, 4(%esp)
Wie kommst du denn auf deine Offsets 8 und 12?
Wenn du deine Parameter im Stack nochmal drauflegen willst, machst du das so:
Code: Alles auswählen
# as --32 -o out.o pars.S
# ld -m elf_i386 out.o
# ./a.out
.text
.code32
.global _start
_start:
pushl $1337
pushl $4223
movl %esp, %ebp
subl $8, %esp
movl 0(%ebp), %eax
movl %eax, 0(%esp)
movl 4(%ebp), %eax
movl %eax, 4(%esp)
Was genau versuchst du denn zu erreichen?
Was für ein System verwendest du?
Wie kompilierst du?
Wenn du für 64-bit kompilierst, scheint die Form wie du Register pushed nicht mehr gültig zu sein:
http://www.x86-64.org/documentation/assembly.html
Architekt hat geschrieben:Edit:
Ups völlig falsches Forum.. Kann das jemand verschieben?

Done.
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 1:57 pm
von Architekt
Ich verwende 32 Bit Gnu Assembler und möchte Variablen als Parameter an eine Funktion übergeben. Diese Funktion soll sie (in diesem Fall) addieren und das Resultat zurückgeben.
8 und 12 als Offset habe ich gelesen und es funktioniert ja auch, solange ich nur Zahlen pushen. Aber für Register und Offsets gilt es nicht mehr.. Und ich weiß nicht warum.

Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 4:23 pm
von Architekt
Hier mal ein minimales Beispiel:
Code: Alles auswählen
.text
.globl _alpha_main
_alpha_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $42, 0(%esp)
movl $23, 4(%esp)
pushl 0(%esp)
pushl 4(%esp)
call _add
addl $8, %esp
addl $8, %esp
popl %ebp
ret
.globl _add
_add:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
# Begin Parameters
movl 4(%ebp), %eax
movl %eax, 0(%esp)
movl 8(%ebp), %eax
movl %eax, 4(%esp)
# End Parameters
# a
pushl 0(%esp)
call _println_int
addl $4, %esp
# b
pushl 4(%esp)
call _println_int
addl $4, %esp
addl $8, %esp
popl %ebp
ret
Und die "runtime":
Code: Alles auswählen
#include <stdio.h>
void println_int(int num) {
printf("%d\n", num);
}
extern void alpha_main();
int main() {
alpha_main();
}
Ich würde 42 und 23 als Ausgabe erwarten, bekomme aber
4200065
42
Ändere ich es wie zuvor auf die offsets 8 und 12 bekomme ich zweimal die 42 als Ausgabe.
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 6:01 pm
von nufan
Architekt hat geschrieben:Ändere ich es wie zuvor auf die offsets 8 und 12 bekomme ich zweimal die 42 als Ausgabe.
Das liegt daran:
Architekt hat geschrieben:
Du legst das oberste Element nochmal oben drauf. pushl korrigiert dein %esp, also greifst du mit 4(%esp) wieder auf das gleiche Element am Stack zu.
Willst du das zweite Element, müsstest du einen Offset von 8 verwenden:
Und in der anderen Reihenfolge:
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 6:10 pm
von Architekt
Das versteh ich nicht. Inwiefern (und warum) korrigiert pushl mein %esp? o.O
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 6:13 pm
von nufan
Architekt hat geschrieben:Das versteh ich nicht. Inwiefern (und warum) korrigiert pushl mein %esp? o.O
%esp zeigt immer auf das oberste Element auf deinem Stack. Wenn du mit pushl was drauf legst, hast du ein neues oberstes Element und musst %esp entsprechend korrigieren.
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 6:37 pm
von Architekt
Ah, verstehe. Das macht mein Vorhaben natürlich schwierig.
Ich evaluiere meine Expressions immer so, dass sie in %eax gepackt werden und mein eigentlicher Plan war, dann immer %eax zu pushen. Aber das klappt ja dann nicht, weil ich durch den push jedesmal %esp und damit die Variablen offsets verändere... Wie kann ich das den geschickt anstellen?
Also der bisherige (fehlerhafte) Output sieht so aus:
# Begin VarExpr
movl 0(%esp), %eax
# End VarExpr
pushl %eax
# Begin VarExpr
movl 4(%esp), %eax
# End VarExpr
pushl %eax
call _add
addl $8, %esp
edit:
Anders gefragt: Kann ich auf den Stack etwas drauf packen, ohne push und trotzdem ohne weitere offsets zu reservieren?
Oder gibt es einen eleganten Lösungsweg, um Argumente an eine Funktion zu übergeben?
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 6:58 pm
von nufan
Architekt hat geschrieben:Anders gefragt: Kann ich auf den Stack etwas drauf packen, ohne push und trotzdem ohne weitere offsets zu reservieren?
Naja sicher geht das irgendwie, ich würde das ehrlich gesagt aber lassen. Da kommt ein Offset-Chaos raus.
Architekt hat geschrieben:Oder gibt es einen eleganten Lösungsweg, um Argumente an eine Funktion zu übergeben?
Der übliche Weg ist Parameter mit push auf den Stack zu legen und in der Funktion mit pop wieder runter zu nehmen.
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 7:02 pm
von Architekt
Was ja in meinem Fall ein Problem ist.
Wenn ich add(a + 2, b + 4) aufrufe (mit a = 0(%esp) und b = 4(%esp)) errechne ich zwei temporäre Werte die in %eax gespeichert werden. Wie soll ich das pushen? Pushe ich beim ersten mal %eax hoch, habe ich beim zweiten mal ein offset Problem, denn b ist nun nicht mehr an Stelle 4 sondern an Stelle 8, was aber meine Expression ja gar nicht wissen kann.
Also entweder ich muss beim jedem Call meinen AST manipulieren (was gar nicht geht) oder ich muss irgendwie einige Offsets freihalten und großzügig Speicher reservieren, damit ich meine Parameter dann wie Variablen behandel... Ist ja großer Mist.