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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.