Seite 2 von 4
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 7:07 pm
von Architekt
Ich habe gerade nochmal aus lauter Verzweiflung ein wenig herumprobiert, und es scheint, dass das hier funktioniert:
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)
movl 0(%esp), %eax
movl %eax, -4(%esp)
movl 4(%esp), %eax
movl %eax, -8(%esp)
call _add
# addl $8, %ebp
addl $8, %esp
popl %ebp
ret
.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
# 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
Das kann ich mir jedoch nicht erklären: negative offset Values bei %esp?
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 7:16 pm
von nufan
Architekt hat geschrieben:Das kann ich mir jedoch nicht erklären: negative offset Values bei %esp?
Das stimmt schon so, der Stack wächst ja in Richtung Adresse 0. Werte oben im Stack haben also niedrigere Adressen also jene darunter.
Das was du da gemacht hast, ist genau was ich vorhin als "Offset-Chaos" bezeichnet habe. Die Lösung funktioniert, ich finde sie aber nicht sehr schön.
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 7:20 pm
von Architekt
Hast du vllt. eine bessere? :/
edit:
Nein, sie funktioniert doch nicht:
Code: Alles auswählen
movl $42, 0(%esp)
movl $23, 4(%esp)
movl 0(%esp), %eax
pushl $2
imull 0(%esp), %eax
addl $4, %esp
movl %eax, -4(%ebp)
0(%esp) ist weiterhin 42, doch 4(%esp) ist jetzt 84, der Wert von b ist somit korrumpiert, was ich ja eig. vermeiden wollte.
Ich glaube ich habe wirklich nur die Wahl, extra Speicher zu reservieren und dort die Parameter zu speichern, oder? Alles andere korrumpiert den Stack...
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 7:41 pm
von Architekt
Hier mal was ich damit meine (so macht es afaik auch der GNU Compiler):
Code: Alles auswählen
.text
.globl _alpha_main
_alpha_main:
pushl %ebp
movl %esp, %ebp
subl $20, %esp # reserve 0, 4 and 8 offset for parameter
movl $42, 12(%esp)
movl $23, 16(%esp)
movl 12(%esp), %eax
pushl $2
imull 0(%esp), %eax
addl $4, %esp
# push param 1
movl %eax, 0(%esp)
movl 16(%esp), %eax
pushl $4
imull 0(%esp), %eax
addl $4, %esp
# push param 2
movl %eax, 4(%esp)
call _add
# check old values
movl 12(%esp), %eax
pushl %eax
call _println_int
addl $4, %esp
movl 16(%esp), %eax
pushl %eax
call _println_int
addl $4, %esp
addl $20, %esp
popl %ebp
ret
.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
# 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
Im Gegensatz zum GNU Compiler habe ich leider keine Wahl um zu sehen, wie viele Parameter maximal vorkommen und muss daher eine gewisse Anzahl an Offsets freilassen, in diesem Beispiel jetzt lediglich 3.
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 8:15 pm
von nufan
Entsprechend der gängigen C-Konventionen würde ich das ganze so machen:
Code: Alles auswählen
.text
.extern _println_int
.globl _alpha_main, _add
_alpha_main:
pushl %ebp
movl %esp, %ebp
movl $42, %eax
movl $23, %ebx
pushl %ebx
pushl %eax
call _add
addl $8, %esp
popl %ebp
ret
_add:
pushl %ebp
movl %esp, %ebp
pushl %ebx
# Begin Parameters
movl 12(%ebp), %eax
movl 8(%ebp), %ebx
# End Parameters
# a
pushl %eax
call _println_int
addl $4, %esp
# b
pushl %ebx
call _println_int
addl $4, %esp
popl %ebx
popl %ebp
ret
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 8:26 pm
von Architekt
Sprich Register benutzten? Dann ist man ja aber auf 4 Parameter (%eax, %ebx, %ecx, %edx) begrenzt.
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 8:37 pm
von nufan
Architekt hat geschrieben:Sprich Register benutzten? Dann ist man ja aber auf 4 Parameter (%eax, %ebx, %ecx, %edx) begrenzt.
Was ist an meiner Version begrenzt? Wenn ich mehr Parameter brauche lege ich mir auch die Anzahl auf den Stack und mach eine Schleife. Strukturell bin ich aber nicht eingeschränkt.
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 9:29 pm
von Architekt
Deine Lösung kommt (wie meine bisherige) entweder in Konflikt, indem sie den Stack korrumpiert (weil, wie in meinem Beispiel, 4(%esp) nicht mehr denselben Wert hat) oder aber beschränkt sich auf die 4 Register.
Re: Assembler: Parameter
Verfasst: Sa Nov 08, 2014 10:19 pm
von nufan
Ich hab ehrlich gesagt keine Ahnung wo du eine Beschränkung siehst.
Code: Alles auswählen
.text
.extern _println_int
.globl _alpha_main, _add
_alpha_main:
pushl %ebp
movl %esp, %ebp
movl $42, %eax
movl $23, %ebx
pushl %ebx
pushl %eax
pushl $2
call _add
addl $12, %esp
movl $2, %eax
movl $15, %ebx
movl $32, %ecx
pushl %ecx
pushl %ebx
pushl %eax
pushl $3
call _add
addl $16, %esp
movl $99, %eax
movl $25, %ebx
movl $11, %ecx
pushl %ecx
pushl %ebx
pushl %eax
pushl $0
pushl $1
pushl $2
pushl $3
pushl $4
pushl $5
pushl $6
pushl $7
pushl $8
pushl $9
pushl $13
call _add
addl $56, %esp
popl %ebp
ret
_add:
pushl %ebp
movl %esp, %ebp
pushl %ecx
pushl %esi
movl 8(%ebp), %ecx
lea 12(%ebp), %esi
.loop:
pushl %ecx
pushl (%esi)
call _println_int
addl $4, %esp
popl %ecx
addl $4, %esi
decl %ecx
jnz .loop
popl %esi
popl %ecx
popl %ebp
ret
Re: Assembler: Parameter
Verfasst: So Nov 09, 2014 12:27 am
von Architekt
Sagen wir doch mal du hast sowas hier (weil du dich ja immer auf einzelne Zahlen beschränkst)
Code: Alles auswählen
movl $42, 12(%esp)
movl $23, 16(%esp)
movl 12(%esp), %eax
pushl $2
imull 0(%esp), %eax
addl $4, %esp
# Params 1...
movl 16(%esp), %eax
pushl $4
imull 0(%esp), %eax
addl $4, %esp
# Param 2...
call _add
Was sowas wäre wie
Ich kann das erste nach EDX moven, das nächste zu ECX und so weiter bis ich bei EAX angekommen bin.
Aber was, wenn du mehr als 4 solcher Ausdrücke als Parameter hast? Sowas wie
Was jetzt?
Die ersten 4 kann ich in den Registern unterbringen (wobei selbst das riskant ist, denn evtl. benutzt ich ja Register zur Auswertung der anderen Expressions). Aber spätestens danach muss ich pushen und sobald ich pushe verändere ich den Stack und spätestens in der Auswertung der letzten Expression hätte dann b nicht mehr den ursprünglichen Wert (da ja etwas gepusht wurde).
Verstehst du mein Dilemma nun etwas besser?