Assembler: Parameter

Pascal, Basic und andere nicht aufgelistete
Benutzeravatar
Architekt
Beiträge: 172
Registriert: Sa Mai 24, 2014 12:04 pm

Re: Assembler: Parameter

Beitrag von Architekt » Sa Nov 08, 2014 7:07 pm

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?

nufan
Wiki-Moderator
Beiträge: 2515
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Assembler: Parameter

Beitrag von nufan » Sa Nov 08, 2014 7:16 pm

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.

Benutzeravatar
Architekt
Beiträge: 172
Registriert: Sa Mai 24, 2014 12:04 pm

Re: Assembler: Parameter

Beitrag von Architekt » Sa Nov 08, 2014 7:20 pm

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...

Benutzeravatar
Architekt
Beiträge: 172
Registriert: Sa Mai 24, 2014 12:04 pm

Re: Assembler: Parameter

Beitrag von Architekt » Sa Nov 08, 2014 7:41 pm

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.

nufan
Wiki-Moderator
Beiträge: 2515
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Assembler: Parameter

Beitrag von nufan » Sa Nov 08, 2014 8:15 pm

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

Benutzeravatar
Architekt
Beiträge: 172
Registriert: Sa Mai 24, 2014 12:04 pm

Re: Assembler: Parameter

Beitrag von Architekt » Sa Nov 08, 2014 8:26 pm

Sprich Register benutzten? Dann ist man ja aber auf 4 Parameter (%eax, %ebx, %ecx, %edx) begrenzt. ;)

nufan
Wiki-Moderator
Beiträge: 2515
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Assembler: Parameter

Beitrag von nufan » Sa Nov 08, 2014 8:37 pm

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.

Benutzeravatar
Architekt
Beiträge: 172
Registriert: Sa Mai 24, 2014 12:04 pm

Re: Assembler: Parameter

Beitrag von Architekt » Sa Nov 08, 2014 9:29 pm

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.

nufan
Wiki-Moderator
Beiträge: 2515
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Assembler: Parameter

Beitrag von nufan » Sa Nov 08, 2014 10:19 pm

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

Benutzeravatar
Architekt
Beiträge: 172
Registriert: Sa Mai 24, 2014 12:04 pm

Re: Assembler: Parameter

Beitrag von Architekt » So Nov 09, 2014 12:27 am

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

Code: Alles auswählen

add(a * 2, b * 4)
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

Code: Alles auswählen

add(a * 2, b * 4, a + 4, b + 3, a - 1, b / 2)
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? ;)

Antworten