Forum: Compiler & IDEs Parameterübergabe an ASM-Funktion in AVR-GCC


von Yaro G. (yaro)


Lesenswert?

Hallo Leute,
Ich bin gerade dabei eine ASM-Funktion zu schreiben und sie in mein 
C-code einzubinden. Ich muss 18 Parameter übergeben, was bedeutet, dass 
9 von denen auf dem Stack landen.
Meine Frage ist nun: wo auf dem Stack finde ich sie? Theoretisch sollte 
ja der Y-Pointer als frame-pointer darauf zeigen, praktisch ist es aber 
so, dass komischerweise der Z-Pointer darauf zeigt. Wie kann man das 
verstehen?
Ich verwende einen ATmega644.
Die Funktion wird von einem Interrupt aufgerufen, könnte dort das 
Problem liegen? Könte es sein, dass der Y-Pointer auf irgendwelche Daten 
zeigt, die dem Interrupt übergeben wurden? (eigentlich wird an 
Interrupts doch garnichts übergeben!?). Und wie kommt der Z-Pointer 
dazu, auf die Parameter der Funktion zu zeigen?
Debugt habe ich mit AVR-Studio.

Ich hoffe, jemand weis Rat.
Gruß, Yaro

von Klaus W. (mfgkw)


Lesenswert?

Schreib doch einfach eine C-Funktion, die die Parameter entgegennimmt
und wieder für jeden der Parameter irgendwas aufruft (damit der Compiler
nichts wegoptimieren kann).

Davon das Listing anschauen und die eigene Funktion genauso
anfangen und enden lassen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Yaroslav Gevorkov schrieb:
> Hallo Leute,
> Ich bin gerade dabei eine ASM-Funktion zu schreiben und sie in mein
> C-code einzubinden. Ich muss 18 Parameter übergeben, was bedeutet, dass
> 9 von denen auf dem Stack landen.
> Meine Frage ist nun: wo auf dem Stack finde ich sie?

Überhaupt nicht. avr-gcc definiert den Frame-Poiner (FP) als 
Stack-Pointer (SP), also FP:=SP. Was du aber brauchst wäre der Wert des 
Argument-Pointers, dessen Offset zum SP du aber nicht kennst. Er ist 
abhängig von der PC-Größe (bekannt), ob es einen FP gibt oder nicht 
(auch bekannt, FP kann man erzwingen) und von der Anzahl der zu 
sichernen Register (unbekannt).

Nachzulesen in ./gcc/config/avr/avr.c:avr_initial_elimination_offset()
    http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/avr.c?revision=149519

> Theoretisch sollte
> ja der Y-Pointer als frame-pointer darauf zeigen,

nö. wer sagt denn sowas?

> Die Funktion wird von einem Interrupt aufgerufen, könnte dort das
> Problem liegen?> Könte es sein, dass der Y-Pointer auf irgendwelche Daten
> zeigt, die dem Interrupt übergeben wurden?

nö. es sei denn, du rufst eine ISR als Funktion auf. Das solltest du 
nicht tun ;-)

> Und wie kommt der Z-Pointer dazu, auf die Parameter der Funktion zu zeigen?

Da frag mal deine Kristallkugel.

> Ich hoffe, jemand weis Rat.

Überleg dir ein gscheites Interface und keines mit wahnsinnigen 18 (in 
Worten: achtzehn!) Parametern!

Mach das Zeug in eine Struktur und übergib nen Zeiger darauf. Das gibt 
nebenbei auch besseren Code.

Des weiteren gibt's die Möglichkeit, das Zeug per varargs zu übergeben 
und die Funktion mit der Adresse der Argumente aufzurufen (va_args, 
avr-gcc übergibt alle vararg-Args via Stack)

Falls du den Code nicht ändern kannst/darfst musst du avr-gcc erweitern 
um an den Offset dranzukommen. Das geht am besten durch Definition eines 
RTL-Builtins wie __builtin_argument_address oder so. Wird aber etwas 
mühsam für dich, weil es momentan noch keine Target-Builtins für avr-gcc 
gibt, d.h. du musst erst das ganze Builtin-Framework klöppeln.

Johann

von Yaro G. (yaro)


Lesenswert?

Das mit dem Array wäre natuerlich eine viel bessere Lösung. So werde ich 
es wahrscheinlich jetzt auch machen.
Zwischenzeitlich habe ich es aber auch anders gelöst bekommen:
Der Stack-Pointer zeigt auf die Rücksprungadresse, dahinter liegen auch 
schon die Parameter. Also habe ich einfach die Adresse des Stackpointers 
gespeichert und um 3 erhöht und war dann direkt bei den Parametern.

Jetzt werde ich es aber auf ein Array umschreiben.
Danke für die schnelle Hilfe!

Gruß, Yaro

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Yaroslav Gevorkov schrieb:

> Zwischenzeitlich habe ich es aber auch anders gelöst bekommen:
> Der Stack-Pointer zeigt auf die Rücksprungadresse, dahinter liegen auch
> schon die Parameter. Also habe ich einfach die Adresse des Stackpointers
> gespeichert und um 3 erhöht und war dann direkt bei den Parametern.

Nein. Das ist keine Lösung, das ich Hack.
Das es funktioniert ist mehr oder weniger Zufall.

Johann

von (prx) A. K. (prx)


Lesenswert?

Johann L. schrieb:

> Überhaupt nicht. avr-gcc definiert den Frame-Poiner (FP) als
> Stack-Pointer (SP), also FP:=SP. Was du aber brauchst wäre der Wert des
> Argument-Pointers, dessen Offset zum SP du aber nicht kennst. Er ist
> abhängig von der PC-Größe (bekannt), ob es einen FP gibt oder nicht
> (auch bekannt, FP kann man erzwingen) und von der Anzahl der zu
> sichernen Register (unbekannt).

Das gilt aber doch wohl nur für C Funktionen selbst. Wer seine Funktion 
in Assembler komplett selber strickt muss sich normalerweise nur darüber 
Gedanken machen, welche Parameter in welchen Register oder wieweit 
entfernt vom SP beim Einsprung stehen, bei AVRs abhängig von der Breite 
des PC 2 oder 3 Bytes. Den Rest entscheidet der Programmierer selber.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

A. K. schrieb:
> Johann L. schrieb:
>
>> Überhaupt nicht. avr-gcc definiert den Frame-Poiner (FP) als
>> Stack-Pointer (SP), also FP:=SP. Was du aber brauchst wäre der Wert des
>> Argument-Pointers, dessen Offset zum SP du aber nicht kennst. Er ist
>> abhängig von der PC-Größe (bekannt), ob es einen FP gibt oder nicht
>> (auch bekannt, FP kann man erzwingen) und von der Anzahl der zu
>> sichernen Register (unbekannt).
>
> Das gilt aber doch wohl nur für C Funktionen selbst. Wer seine Funktion
> in Assembler komplett selber strickt muss sich normalerweise nur darüber
> Gedanken machen, welche Parameter in welchen Register oder wieweit
> entfernt vom SP beim Einsprung stehen, bei AVRs abhängig von der Breite
> des PC 2 oder 3 Bytes. Den Rest entscheidet der Programmierer selber.

Ja, stimmt. Sonst kätte der Callee ja auch keine Chance den Offset zu 
berechnen. Danke für die Korrektur.

Eine Funktion mit 18 Parametern zu haben find ich dennoch grenzwertig. 
Vor allem weil man viele der Parameter ohnehin sichern muss weil sie 
call-saved (d.h. callee-saved) sind.

Johann

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.