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
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.
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?
nö
> 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
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
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
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.
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
Eine eigene Frage?
Dieser Thread ist über 17 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.