www.mikrocontroller.net

Forum: Compiler & IDEs Stack in C manipulieren


Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich arbeite mit einem Atmega168 und programmiere in C.
Ich möchte in einem Interrupt den Stackpointer so manipulieren, das nach 
dem beendigen des Interrupts ein Unterprogramm eingeschoben wird.
Es soll also nicht zum eigentlichen Programmablauf zurückgekehrt werden, 
sondern erst ein Unterprogramm ausgeführt werden und dann zum 
Ursprünglichen Programmteil zurückgekehrt werden.
Nun meine Fragen:
Ist so etwas nur mit Assembler möglich?
Kann mir jemand Auskunft über die Stack Verwaltung geben?
Wie kann ich zum Beispiel ein „push“ oder „pop“ in C durchführen?
Legt C immer als letztes die Rücksprungadresse auf den Stack?

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum packst Du das nicht direkt (eventl. als Funktionsaufruf) in die 
entsprechende ISR? Nebenbei, wozu das ganze?

-->http://www.mikrocontroller.net/articles/AVR-GCC-Tu...
(--> http://www.mikrocontroller.net/articles/AVR-Tutori... in 
ASM)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du schreibst jetzt 100 mal:
  "Ich soll den Stack in C nicht manipulieren"

Die Verwaltung des Stacks, des Speichers obliegt einzig
und alleine dem Compiler. Wenn du dich da einmischt, wird
alles nur noch schlimmer.

Wenn du am Ende einer ISR eine Funktion aufgerufen haben
möchtest, dann ruf sie doch in Gottes Namen auf.
Wenn die Absicht darin besteht, dass du Interrupts zugelassen
haben willst, während die Funktion arbeitet, dann gib halt
in Allahs Namen die Interrupts vor dem Aufruf der Funktion
frei.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum sollte man das so tun?

Warum nicht das "Unterprogramm" (Du meinst vermutlich eine Funktion) aus 
der Interruptroutine heraus aufrufen?
void meineFunktion(void)
{
  // tut irgendwas 
}

__interrupt__ meineInterruptFunktion(void)
{
  // tut irgendwas wichtiges

  // hier als letztes aus der Interruptroutine die wichtige 
  // Funktion aufrufen
  meineFunktion();
}


Davon abgesehen gäbe die Vorgehensweise Probleme. Zwar ist es möglich 
(mit Assembler-Mitteln), die auf dem Stack liegende Rücksprungadresse zu 
manipulieren, aber dann wird beim Verlassen des Interrupts bereits der 
Prozessorzustand (Registerinhalte etc.) in den Zustand versetzt, in dem 
er bei Eintreffen des Interrupts war - Dein "Unterprogramm" kann damit 
gar nichts anfangen, und außerdem müsste das "Unterprogramm" dann auch 
dafür sorgen, daß nichts von diesem Zustand verändert wird.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiko wrote:

> Legt C immer als letztes die Rücksprungadresse auf den Stack?

Nein, natürlich als erstes. Und dann werden einige Register gesichert.

Du hast also sehr schlechte Karten, herauszufinden, wo die Retunradresse 
liegt.

Ist aber auch garnicht nötig, schreib einfach "sei();" und dahinter den 
Funktionsaufruf.


Peter

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na gut, dann werde ich den aufgerufenen Interrupt sperren, den globalen 
Interrupt wieder freigeben und dann die Funktion aufrufen.
Ich dachte nur, ich könnte das evtl. auch anders erledigen! Mein Fehler!

@Karl Heinz:
"Ich soll den Stack in C nicht manipulieren"
"Ich soll den Stack in C nicht manipulieren"
"Ich soll den Stack in C nicht manipulieren"
....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiko wrote:
> @Karl Heinz:
> "Ich soll den Stack in C nicht manipulieren"
> "Ich soll den Stack in C nicht manipulieren"
> "Ich soll den Stack in C nicht manipulieren"
> ....

Das ist die falsche Einstellung :-)

Die Richtige wäre gewesen
#include <stdio.h>

int main()
{
  int i;

  for( i = 0; i < 100; ++i )
    printf( "Ich soll den Stack in C nicht manipulieren\n" );
}

:-)  :-)

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heiko wrote:
> Na gut, dann werde ich den aufgerufenen Interrupt sperren, den globalen
> Interrupt wieder freigeben und dann die Funktion aufrufen.

Das bewirkt dann aber etwas völlig anderes, als die Stackmanipulation!

Mit Stackmanipulation würde der Interrupt nicht gesperrt und er könnte 
wärend des Unterprogramms wieder eintreten.
Es könnten also 2 (oder mehr) Instanzen des Unterprogramms gleichzeitig 
laufen.


Peter

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Legt C immer als letztes die Rücksprungadresse auf den Stack?
> Nein, natürlich als erstes. Und dann werden einige Register gesichert.

Nur um pingelig zu sein : das "Auf den Stack legen" der 
Rücksprungadresse, bzw. Statusregister bei einem Interrupt oder 
Funktionsaufruf macht der Prozessor, also die Hardware, und hat mit der 
Programmiersprache nichts zu tun.

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter: ja..

@Klaus: der Prozessor führt die Befehle aus, die ein Programm zum Inhalt 
hat, was wiederum ein Produkt des Compiler und Linker ist.

Autor: Klaus Falser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Der Prozessor führt die Befehle aus, die ein Programm zum Inhalt
> hat, was wiederum ein Produkt des Compiler und Linker ist.

Ääähh, jetzt wirds philosophisch, aber der Prozessor führt den CALL 
Befehl aus, welcher die Rücksprungadresse (= aktueller Programmzähler + 
x) als Low-Byte und High-Byte) auf den Stack legt, und die Adresse der 
angesprungenen Funktion in den Programmzähler lädt. Das ist EIN Befehl, 
und schaut immer gleich aus, egal ob Assembler, C oder Pascal.
Dasselbe gilt für die Interrupts, bei dem die HARDWARE den aktuellen 
Pogrammzähler und bei manchen Prozessoren auch das Statusregister auf 
den Stack legt. Die Reihenfolge, in der dies auf den Stack gelegt wird, 
ist nur vom Prozessor bestimmt, und nicht von der verwendeten 
Programmiersprache.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Ansatz von Heiko ist so dumm nicht, er erinnert an top half / bottom 
half interrupt handlers komplexerer Interrupt-Systeme. Aber in C kann 
man das vergessen, das geht nicht.

Dazu kommt, dass die Routine, die dabei eingeschoben werden soll, 
ähnlichen Regeln unterliegt wie ein Interrupt-Handler. Denn sie muss 
alle Register sichern.

Fragt sich aber, wie eilig es mit dem Aufruf dieses bottom half handlers 
ist. Wenn der nicht zwingend direkt danach erfolgen muss, gibt es andere 
Methoden.

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Kaiser wrote:
> Der Ansatz von Heiko ist so dumm nicht, er erinnert an top half / bottom
> half interrupt handlers komplexerer Interrupt-Systeme. Aber in C kann
> man das vergessen, das geht nicht.
>
> Dazu kommt, dass die Routine, die dabei eingeschoben werden soll,
> ähnlichen Regeln unterliegt wie ein Interrupt-Handler. Denn sie muss
> alle Register sichern.
>
> Fragt sich aber, wie eilig es mit dem Aufruf dieses bottom half handlers
> ist. Wenn der nicht zwingend direkt danach erfolgen muss, gibt es andere
> Methoden.

Also mir ist nicht ganz klar, was mit dem top-half bzw. bottom-half 
handler gemeint ist. Ich ahne aber, dass sich die Frage des 
Ursprungsposters auf ein ähnliches Problem wie das meine bezieht.

Nehmen wir mal abstrakt folgendes an:

Der Controller soll drei völlig voneinander unabhängige Aufgaben A, B, C 
erfüllen können. Dafür gibt es auch drei eigene Programmteile, oder 
genauer drei eigenständige Programme, die auch völlig unabhängig 
voneinander funktionieren.
Eine weitere Funktion ermöglicht beim Start des Controllers die Auswahl 
welche der drei Aufgaben erfüllt werden soll.
Soweit werden keinerlei Interrupts benutzt.

Nun möchte ich aber durch einen Eingang (Taster) zwischen den drei 
"Aufgaben" wechseln, ohne dass ich dazu den Sourcecode der drei 
Programme selbst modifizieren kann oder will. Ich kann dort also nicht 
den Taster abfragen.
Das wäre per Interrupt natürlich sehr einfach zu machen. Bislang habe 
ich die Kommunikation zwischen ISR und Hauptprogramm immer mittels 
volatile Variablen gelöst. Aber das bringt mich hier nicht weiter, weil 
ich diese ja dann auch permanent prüfen müsste bzw. den Sourcecode der 
drei Programme modifizieren müsste.
Einfacher wäre es, wenn ich nach Ende der ISR zum jeweiligen Programm 
springen könnte. Wenn ich hier einfach sei(); A/B/C(); aufrufen würde, 
läuft aber doch irgendwann der Stack voll, oder?

Wie macht man sowas "richtig"?

Viele Grüße,
Klaus

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hinweis: der Originalbeitrag ist mehr als 6 Monate alt.

>Der Controller soll drei völlig voneinander unabhängige Aufgaben A, B, C
>erfüllen können.

Dafür würde ich Zustandsautomaten ('state machine') verwenden, die 
abhängig von eine Variablen aktiviert oder stillgelegt werden. Im 
Interrupt wird dabei aber nicht mehr herumgewuschtelt.

Wenn Kosten-Nutzen stimmen, kann man auch ein Betriebssystem dafür 
verwenden ....

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
> Hinweis: der Originalbeitrag ist mehr als 6 Monate alt.
>
>>Der Controller soll drei völlig voneinander unabhängige Aufgaben A, B, C
>>erfüllen können.
>
> Dafür würde ich Zustandsautomaten ('state machine') verwenden, die
> abhängig von eine Variablen aktiviert oder stillgelegt werden. Im
> Interrupt wird dabei aber nicht mehr herumgewuschtelt.
>
> Wenn Kosten-Nutzen stimmen, kann man auch ein Betriebssystem dafür
> verwenden ....

Naja, nur wie gesagt, ist das ja alles schon fertig. Ich möchte das 
Programm einfach gerne "von außen" per Interrupt unterbrechen ohne dass 
das Programm selbst etwas davon merkt.

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus W. wrote:

> Naja, nur wie gesagt, ist das ja alles schon fertig. Ich möchte das
> Programm einfach gerne "von außen" per Interrupt unterbrechen ohne dass
> das Programm selbst etwas davon merkt.

Äh, also zur Ergänzung:

Eher abbrechen statt unterbrechen! Es müssen dabei keine Zustände 
(Stack, Speicher, Register o.ä.) gesichert werden. Jeder Programmteil 
startet nach dem Interrupt komplett neu mit Initialisierung usw...

Autor: G. O. (aminox86)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin gerade auf den Thread gestossen und kann mit eine kleine Stapelei 
nicht verkneifen.

 #define STAPEL 0
 void fun1(void);
 void fun2(int i);

  int main(void)
 {
   fun1();
   puts("zurück aus fun1- oder wars doch fun2?");
   return(0);
 }

 void fun1(void)
 { int i;

   fun2(i);
   puts("in fun1");
 }

 void fun2(int i)
 { int *stapel;

   puts("in fun2");
   #if STAPEL
   stapel=&i-1;
   *stapel=*stapel+4;
   #endif
 }

;-)

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerhardt O. wrote:
> Bin gerade auf den Thread gestossen und kann mit eine kleine Stapelei
> nicht verkneifen.

hm...

klaus@hermes:~/work$ gcc -o test test.c
klaus@hermes:~/work$ ./test
in fun2
hæž@\žpî·PÏò·
zurück aus fun1- oder wars doch fun2?

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sachtma, gabs für so Viecher nich kleine RTOS..? Also quasi kleine 
"Kernel", die das alles erledigen?

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Eher abbrechen statt unterbrechen!

Wenn man eine Unterbrechung nicht fortsetzt, ist es ein Abbruch. Wenn 
man eine 'state machine' z.B. mit Zustand INIT neu startet, kann man 
auch alles neu initialisieren lassen.

Diese Aktionen direkt aus einer Interruptroutine zu veranlassen, würde 
ich nicht (besser nie) machen. Der Umfang Deiner Funktionen ist mir 
nicht bekannt, scheint aber eher "bescheiden" zu sein ;-)

Betriebssystem -> RTOS; muß aber nicht unbedingt sein.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um eine laufendes Programm zu unterbrechen, und völlig von vorne 
anzufangen, haben alle Mikroprozessoren einen speziellen Pin - genannt 
Reset.

Was danach passieren soll, kannst du selber per Programm bstimmen.

Wo also ist das Problem?

Oliver

Autor: G. O. (aminox86)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@texmex
Ich will natürlich keinen zweifelhaften Code in die Welt setzen, das 
Programmfragment ist leider fehlerhaft. Im Anhang der korrigierte Code.
Sollte sich mit jedem Ansi-C Compiler compilieren lassen, allerdings 
darf der zugewiesene Adressraum nicht größer als 64k sein. Die 
Stapelmanipulation funktioniert in diesem Fall nicht mehr.
mfg

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerhardt O. wrote:
> @texmex
> Ich will natürlich keinen zweifelhaften Code in die Welt setzen, das

Naja, ein bischen zweifelhaft ist er schon :-).

Scheint auch nicht so ganz ausgereift:
klaus@hermes:~/work$ gcc -o stapel stapel.c
klaus@hermes:~/work$ ./stapel 
in fun2
Ungültiger Maschinenbefehl
klaus@hermes:~/work$

Naja, aber ernsthaft: Klar kann man den Stack vielleicht auch in C 
irgendwie zurechtbiegen, aber gerade solche dirty tricks wollte ich ja 
eigentlich vermeiden. Die Frage ist eher, ob es eine vernünftige Lösung 
gibt. In Assembler wäre das mit ein paar Zeilen zu machen...

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver wrote:
> Um eine laufendes Programm zu unterbrechen, und völlig von vorne
> anzufangen, haben alle Mikroprozessoren einen speziellen Pin - genannt
> Reset.

Auf den Hinweis habe ich ja gewartet :-).
Grundsätzlich hast du natürlich recht. Wenn der Controller aber nach dem 
Reset unterschiedliche Dinge tun soll, die von Bedingungen VOR dem Reset 
abhängen, müsste man schon allerlei drumherum basteln. Und wie ich das 
dem C-Compiler beibringe, ist mir schon eher schleierhaft.

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
>>Eher abbrechen statt unterbrechen!
>
> Wenn man eine Unterbrechung nicht fortsetzt, ist es ein Abbruch. Wenn
> man eine 'state machine' z.B. mit Zustand INIT neu startet, kann man
> auch alles neu initialisieren lassen.
Genau so ist es.

> Diese Aktionen direkt aus einer Interruptroutine zu veranlassen, würde
> ich nicht (besser nie) machen. Der Umfang Deiner Funktionen ist mir
> nicht bekannt, scheint aber eher "bescheiden" zu sein ;-)

Naja, "bescheiden" ist relativ. Es handelt sich im Grunde um eigene 
Programme, mit einer eigenen main() funktion. Der Punkt ist aber vor 
allem der, dass ich daran nichts modifizieren möchte.

> Betriebssystem -> RTOS; muß aber nicht unbedingt sein.

Kaum. Da ich ja nie nach einem Abbruch in das andere Programm 
zurückkehren muss.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>In Assembler wäre das mit ein paar Zeilen zu machen...

Dann zeige uns bitte diese Zeilen!

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
>>In Assembler wäre das mit ein paar Zeilen zu machen...
>
> Dann zeige uns bitte diese Zeilen!

Naja, ich muss doch nur den Stackpointer zurücksetzen und die 
Rücksprungadresse auf die Startadresse des neuen Programms setzen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus W. wrote:

> Naja, "bescheiden" ist relativ. Es handelt sich im Grunde um eigene
> Programme, mit einer eigenen main() funktion. Der Punkt ist aber vor
> allem der, dass ich daran nichts modifizieren möchte.

Wenn es immer noch um den AVR geht, dann geht das nicht.
Der kann keine virtuelle CPU emulieren.

Es darf nur ein main geben, basta.

Du mußt die Programme z.B. in main1, main2, main3 usw. umbenennnen und 
im richtigen main machst Du dann einfach die Auswahl.

Und Du mußt natürlich alles zusammen linken.


Peter

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Es handelt sich im Grunde um eigene Programme, mit einer eigenen main() 
>funktion.

Na, dann dürfte das erste Problem, welches du angehen solltest, sein, 
einen Weg zu finden, wie du die drei Programme zusammengebastelt 
bekommst. Über den normalen C-Compiler/Linker wird das wohl nicht gehen, 
für drei globale Funktionen mit dem schönen Namen main() in einem 
Programm braucht es schon Java. Da geht das.

Oliver

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger wrote:
> Klaus W. wrote:
>
>> Naja, "bescheiden" ist relativ. Es handelt sich im Grunde um eigene
>> Programme, mit einer eigenen main() funktion. Der Punkt ist aber vor
>> allem der, dass ich daran nichts modifizieren möchte.
>
> Wenn es immer noch um den AVR geht, dann geht das nicht.
> Der kann keine virtuelle CPU emulieren.
>
> Es darf nur ein main geben, basta.
>
> Du mußt die Programme z.B. in main1, main2, main3 usw. umbenennnen und
> im richtigen main machst Du dann einfach die Auswahl.
>
> Und Du mußt natürlich alles zusammen linken.

Ja, das ist völlig klar.

Ich habe mir zwar schon überlegt, ob es nicht möglich wäre, die 
Programme getrennt zu compilieren und dem Linker irgendwie einen Offset 
beizubringen, so dass ich sie hintereinander ins flash legen kann. Dann 
evtl. noch eine kleine resetroutine, welche das jeweilige Programm 
startet.

Aber das ist jetzt abgesehen von der Stack/Interrupt Geschichte schon 
wieder eine andere Baustelle.

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver wrote:
>>Es handelt sich im Grunde um eigene Programme, mit einer eigenen main()
>>funktion.
>
> Na, dann dürfte das erste Problem, welches du angehen solltest, sein,
> einen Weg zu finden, wie du die drei Programme zusammengebastelt
> bekommst. Über den normalen C-Compiler/Linker wird das wohl nicht gehen,
> für drei globale Funktionen mit dem schönen Namen main() in einem
> Programm braucht es schon Java. Da geht das.
>
> Oliver

Naja, siehe oben. Natürlich kann ich einfach main1(), main2(), main3() 
machen. Dann dürfen sich nur andere Symbole (globale Variablen, 
Funktionen usw.) nicht ins Gehege kommen. Deshalb wäre getrennt 
compilieren natürlich schon ganz nett.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da war der Peter wieder schneller...

Egal, mit drei Funktionen mit angepassten mainx()-Namen geht es. Dazu 
eine ISR, die in Abhängigkeit der gedrückten Taste einen Code für die 
nächste aufzurufende mainx()-Aktion ins EEPROM schreibt, und dann einen 
Software-Reset ausführt (oder den Watchdog startet, und wartet, bis der 
zuschlägt). Dazu eine main()-Funktion, die anhand es EEPROM-Codes in die 
richtige Funktion verzweigt.

Oliver

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver wrote:
> Da war der Peter wieder schneller...
>
> Egal, mit drei Funktionen mit angepassten mainx()-Namen geht es. Dazu
> eine ISR, die in Abhängigkeit der gedrückten Taste einen Code für die
> nächste aufzurufende mainx()-Aktion ins EEPROM schreibt, und dann einen
> Software-Reset ausführt (oder den Watchdog startet, und wartet, bis der
> zuschlägt). Dazu eine main()-Funktion, die anhand es EEPROM-Codes in die
> richtige Funktion verzweigt.

Ja, sowas ist mir schon in den Sinn gekommen. Erschien mir dann aber 
auch irgendwie overkill, wenn ich mir vorstelle, dass ich EIGENTLICH nur 
die richtige Adresse in den Stack und den Stackpointer auf die richtige 
Adresse setzen müsste.

Aber so funktioniert es natürlich.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerhardt O. wrote:
> @texmex
> Ich will natürlich keinen zweifelhaften Code in die Welt setzen

Dann lass es bitte. Dein angehängtes Programm ist ein Hack der 
aller-übelsten Sorte. Da kriege ich Kopfschmerzen und Augenschmerzen 
zugleich, wenn ich mir das so anschaue.

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. wrote:

> Dann lass es bitte. Dein angehängtes Programm ist ein Hack der
> aller-übelsten Sorte.

Na und? Solange man es weiss, darf er doch mal etwas spielen :-).
(Abgesehen davon dass es bei mir nicht funktioniert, aber das haben 
solche Programme wohl so an sich :-).

Mal was anderes:

Was passiert eigentlich, wenn ich innerhalb einer interrupt routine 
exit() aufrufe? Gab es da nicht mal ein atexit() wo sich Funktionen bei 
exit() registrieren lassen? Oder geht das nur bei "echtem" Programmende 
(ohne exit())?

Viele Grüße,
Klaus

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Gab es da nicht mal ein atexit() ...

Stimmt, da ga es auch ein change_task(). Damit kann man zwischen 
verschiedenen main() umschalten.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann nimm doch lieber gleich exec().

Das zugehörige linux musst du halt auch noch mal eben auf deinen AVR 
portieren - hoffentlich ist es kein tiny :-)

Oliver

Autor: G. O. (aminox86)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. wrote:
> Gerhardt O. wrote:
>> @texmex
>> Ich will natürlich keinen zweifelhaften Code in die Welt setzen
>
> Dann lass es bitte. Dein angehängtes Programm ist ein Hack der
> aller-übelsten Sorte. Da kriege ich Kopfschmerzen und Augenschmerzen
> zugleich, wenn ich mir das so anschaue.

In einem solchen Fall empfehle ich Aspirin und eine Sehhilfe.

Ab hier wieder konstruktiv.
Der Programmschnipsel zeigt eine, wie ich meine, legale 
Stapelmanipulation, die, und da liegt wohl der Hund begraben, auf einer 
x86-Maschine einwandfrei läuft, wenn unter MSC oder BorlandC compiliert 
wurde.
Das Programm bewirkt lediglich, dass bei aktivierter Stapelmanipulation 
aus der zuletzt aufgerufenen Funktion direkt zu main() zurückgekehrt 
wird.
Diese Technik wurde, in anderer Form, in dem Buch "C-Programmierung..." 
von H.Schildt, erschienen 1990 bei McGraw-Hill, beschrieben.

Mir scheint, irgendwie bin ich im falschen Forum gelandet.
:-(

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerhardt O. wrote:
> Ab hier wieder konstruktiv.
> Der Programmschnipsel zeigt eine, wie ich meine, legale
> Stapelmanipulation, die, und da liegt wohl der Hund begraben, auf einer
> x86-Maschine einwandfrei läuft, wenn unter MSC oder BorlandC compiliert
> wurde.


Siehst du. Das Problem bei der Sache ist, dass du dich in 
Compilerspezifische Sachen einmischst. Und sowas macht man einfach 
nicht. Parameter müssen nicht zwangsläufig über den Stack übergeben 
werden. Für mich ist das schlicht und einfach Missbrauch von Pointern 
zur Lösung eines Problems, dass man viel einfacher und sauberer lösen 
könnte.

Vermutlich funktioniert das Beispiel auch nur unter bestimmten 
Compilerversionen bzw. mit bestimmten Compilerparametern.

Autor: Klaus W. (Firma: privat) (texmex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, also der Abschnitt

   Non-Local Exits

Im glibc manual klingt doch recht viel versprechend:

Sometimes when your program detects an unusual situation inside a deeply 
nested set of function calls, you would like to be able to immediately 
return to an outer level of control. This section describes how you can 
do such non-local exits using the setjmp and longjmp functions.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerhardt O. wrote:

> Bin gerade auf den Thread gestossen und kann mit eine kleine Stapelei
> nicht verkneifen.

Bitte reduzieren Sie die Anzahl der Zitatzeilen

>  void fun2(int i)
>  { int *stapel;
>
>    puts("in fun2");
>    #if STAPEL
>    stapel=&i-1;
>    *stapel=*stapel+4;
>    #endif
>  }

Ist ein Hack. Du kannst nicht auf allen Maschinen garantieren, dass i 
überhaupt auf dem Stack übergeben wird und dass stapel auf dem Stack 
liegt. Beide Variablen können auch in Registern liegen. Ganz abgesehen 
von der magischen 4.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.