Forum: Mikrocontroller und Digitale Elektronik STM32 Stackpointer


von Steffen W. (surrounder)


Lesenswert?

Hallo Forum,

ich arbeite mit einem STM32F103VBT7 mit Easyeclipse 1.3.1.1 und GCC 
4.4.0, als Debugger verwende ich den HiTOP mit einem Hitex Tantino.

ich muss für eine Anwendung einen Registertest durchführen (Galpath) 
deshalb sind meine Regsiter R0-R12 danach zerstört. Das sollte meiner 
Meinung nach auch kein Problem sein, da diese doch Gerneal Purpose 
Register sind.

Ich habe nun aber ein Problem, denn ich komme aus meiner Routine die den 
Test ausführt nicht mehr zurück in mein Hauptprogramm. Nun kann ich 
natürlich meine Register vorher auf den Stack Pushen (dann funktioniert 
der Rücksprung), das möchte ich aber eigentlich nicht.

Das Problem liegt eindeutig am Register R7, wenn ich dieses unangetatste 
lasse, dann funktioniert mein Code und das Programm läuft wie geplant 
weiter. Sobald ich R7 zerstöre, komme ich wie nicht mehr aus meiner 
Routine zurück.

Im Assembler Code ist mir nun aufgefallen dass mein Programm wenn ich 
das richtig verstehe R7 als das Register verwendet in dem die 
Rücksprungadresse steht?!

mov sp, r7
pop {r7,pc}

Das ist mir nun aber nicht klar, denn eigentlich müsste er doch R13 
verwenden oder?

Zum Compilieren verwende ich ein makefile das ich selber geschrieben 
habe, die Compilerflags sind

CFLAGS  = -c -mcpu=cortex-m3 -mthumb -gdwarf-2 -MD -O0 -trigraphs -Wall 
-fsigned-char -mlittle-endian -xc -mno-thumb-interwork  -mno-tpcs-frame


Hat jemand eine Idee warum das so ist? Ich gehe mal davon aus dass der 
Compiler einen 16 Bit Thumb Befehlt verwendet oder?

Danke für jede Info.

Steffen

von (prx) A. K. (prx)


Lesenswert?

Steffen Walter schrieb:

> ich muss für eine Anwendung einen Registertest durchführen (Galpath)
> deshalb sind meine Regsiter R0-R12 danach zerstört. Das sollte meiner
> Meinung nach auch kein Problem sein, da diese doch Gerneal Purpose
> Register sind.

Es ist nur dann kein Problem, wenn die Register entsprechend dem vom 
Compiler verwendeten ABI behandelt werden, d.h. wenn die vom 
Aufgerufenen zu sichernden Register auch gesichert werden.

Nur ein Teil der Register darf von einer Funktion ad libitum modifizert 
werden. Und auch bei denen kann es passieren, dass man dem Compiler 
gewaltig auf die Füsse tritt, wenn der von dieser Modifikation nichts 
weiss.

Im GCC kann man dessen "asm" Statements mit einer Liste modifizierter 
Register ausstatten, dann macht der Compiler die Verwaltung selber.

von Steffen W. (surrounder)


Lesenswert?

Hallo und danke für die schnelle Antwort. Nur noch einmal 
zusammengefasst damit ich das richtig verstanden habe:

Der Compiler entscheidet welches Register er verwendet um den Rücksprung 
in die Routine aus der ich komme zu machen?

Ich war bisher davon ausgegangen dass der Compiler die Adresse aus der 
ich komme im Stack ablegt und diese dann über den Stackpointer 
zurückliest um sich dann seine Rücksprungadresse zu setzten. Ist das 
nicht so?

Wenn ich mir meinen Assembler Code anschaue, wir dort ja ein MOV 
gemacht. MOV ist ja ein 16 Bit thumb Befehl, kann also nur auf R0-R7 
zugreifen. Warum holt er sich die Adresse nicht vom Stack? Kann ich ihn 
dazu irgendwie zwingen?

Ich habe das Problem momentan so umgangen dass ich vor meinem 
Registertest einen PUSH { R0-R12 } ausführe und danach einen POP { 
R0-R12 }, aber ganz klar warum ich das machen muss ist mir das noch 
nicht.

Gruß

Steffen

von (prx) A. K. (prx)


Lesenswert?

Steffen Walter schrieb:

> Der Compiler entscheidet welches Register er verwendet um den Rücksprung
> in die Routine aus der ich komme zu machen?

Ja.

> Ich war bisher davon ausgegangen dass der Compiler die Adresse aus der
> ich komme im Stack ablegt und diese dann über den Stackpointer
> zurückliest um sich dann seine Rücksprungadresse zu setzten. Ist das
> nicht so?

Nicht so. Kann er machen, kann er lassen.

> Wenn ich mir meinen Assembler Code anschaue, wir dort ja ein MOV
> gemacht. MOV ist ja ein 16 Bit thumb Befehl, kann also nur auf R0-R7
> zugreifen.

Es gibt m.W. auch Codierungen für alle Register.

> Warum holt er sich die Adresse nicht vom Stack? Kann ich ihn
> dazu irgendwie zwingen?

Ja. Den Sourcecode vom GCC entsprechend umschreiben.

> Ich habe das Problem momentan so umgangen dass ich vor meinem
> Registertest einen PUSH { R0-R12 } ausführe und danach einen POP {
> R0-R12 }, aber ganz klar warum ich das machen muss ist mir das noch
> nicht.

Weil das ein bisschen so ist, also ob dir jemand den Stuhl unter dem 
Hintern wegzieht, du unsanft Kontakt mit dem Boden bekommst, und er dich 
anschliessend fragt, warum er das nicht machen dürfte.

Die Entscheidung, welche Register wofür verwendet werden, trifft der 
Compiler selbst, ggf. in Absprache mit einer allgemeinen Konvention. 
Wenn du da reinfunkst ohne ihm das zu sagen, dann kann das eben in die 
Hose gehen.

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.