Forum: Compiler & IDEs Stack in C manipulieren


von Heiko (Gast)


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?

von Micha (Gast)


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-Tutorial#Programmieren_mit_Interrupts
(--> http://www.mikrocontroller.net/articles/AVR-Tutorial:_Interrupts in 
ASM)

von Karl H. (kbuchegg)


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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Warum sollte man das so tun?

Warum nicht das "Unterprogramm" (Du meinst vermutlich eine Funktion) aus 
der Interruptroutine heraus aufrufen?
1
void meineFunktion(void)
2
{
3
  // tut irgendwas 
4
}
5
6
__interrupt__ meineInterruptFunktion(void)
7
{
8
  // tut irgendwas wichtiges
9
10
  // hier als letztes aus der Interruptroutine die wichtige 
11
  // Funktion aufrufen
12
  meineFunktion();
13
}


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.

von Peter D. (peda)


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

von Heiko (Gast)


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

von Karl H. (kbuchegg)


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
1
#include <stdio.h>
2
3
int main()
4
{
5
  int i;
6
7
  for( i = 0; i < 100; ++i )
8
    printf( "Ich soll den Stack in C nicht manipulieren\n" );
9
}

:-)  :-)

von Peter D. (peda)


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

von Klaus F. (kfalser)


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.

von Heiko (Gast)


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.

von Klaus Falser (Gast)


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.

von Andreas K. (a-k)


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.

von Klaus W. (Firma: privat) (texmex)


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

von Gast (Gast)


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

von Klaus W. (Firma: privat) (texmex)


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.

von Klaus W. (Firma: privat) (texmex)


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

von G. O. (aminox86)


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
 }

;-)

von Klaus W. (Firma: privat) (texmex)


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?

von Sven P. (Gast)


Lesenswert?

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

von Gast (Gast)


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.

von Oliver (Gast)


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

von G. O. (aminox86)


Angehängte Dateien:

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

von Klaus W. (Firma: privat) (texmex)


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:
1
klaus@hermes:~/work$ gcc -o stapel stapel.c
2
klaus@hermes:~/work$ ./stapel 
3
in fun2
4
Ungültiger Maschinenbefehl
5
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...

von Klaus W. (Firma: privat) (texmex)


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.

von Klaus W. (Firma: privat) (texmex)


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.

von Gast (Gast)


Lesenswert?

>In Assembler wäre das mit ein paar Zeilen zu machen...

Dann zeige uns bitte diese Zeilen!

von Klaus W. (Firma: privat) (texmex)


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.

von Peter D. (peda)


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

von Oliver (Gast)


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

von Klaus W. (Firma: privat) (texmex)


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.

von Klaus W. (Firma: privat) (texmex)


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.

von Oliver (Gast)


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

von Klaus W. (Firma: privat) (texmex)


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.

von Simon K. (simon) Benutzerseite


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.

von Klaus W. (Firma: privat) (texmex)


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

von Gast (Gast)


Lesenswert?

>Gab es da nicht mal ein atexit() ...

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

von Oliver (Gast)


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

von G. O. (aminox86)


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

von Simon K. (simon) Benutzerseite


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.

von Klaus W. (Firma: privat) (texmex)


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.

von Stefan B. (stefan) Benutzerseite


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.

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.