Forum: Mikrocontroller und Digitale Elektronik Assembler statt C code in start up routinen


von hansi (Gast)


Lesenswert?

hallo,

mal eine frage, welche wohl recht banal erscheinen dürfte, mich aber zum 
grübeln bringt.

Es gibt ja MCUs, da wird, bevor in die main gesprungen wird, eine art 
startup routine ausgeführt, die so grundlegende settings übernimmt, wie 
zB die main clock einzustellen oder den stack zu initialisieren.
Ich Frage mich nun, wieso solche Dateien, oft als Assembler code 
geschrieben werden und nicht in c.

wann muss ich explizit auf Assembler zurückgreifen und wann nicht?

von Loonix (Gast)


Lesenswert?

hansi schrieb:
> Ich Frage mich nun, wieso solche Dateien, oft als Assembler code
> geschrieben werden und nicht in c.

Die Antwort hast du doch oben schon selbst gegeben, daher meine Frage an 
dich: Macht es Sinn etwas in C zu implementieren bevor die C-Runtime, 
respektive der Stack initialisiert sind?

von Düsendieb (Gast)


Lesenswert?

hansi schrieb:
> wann muss ich explizit auf Assembler zurückgreifen und wann nicht?

in dem o.g. Fall auf jeden Fall nicht.

Assembler nur wenn die Anwendung auf den Takt genau zeitkritisch ist, 
oder wenn der Controller bis zu letzt ausnutzt werden soll.

Für alle Anwendungen mit einer Stückzahl kleiner 10 nimmt man einfach 
den nächst größeren Controller und kann dann wieder normal in C 
programmieren.


Axel

von Loonix (Gast)


Lesenswert?

Düsendieb schrieb:
> Assembler nur wenn die Anwendung auf den Takt genau zeitkritisch ist,
> oder wenn der Controller bis zu letzt ausnutzt werden soll.

Antwort passt leider nicht zur Frage (nochmal genau lesen).

von lowlevel (Gast)


Lesenswert?

Es gibt verschiedene Gründe:

1. Assembler ist einfach gängiger und schafft optimierten Code.
2. Du erwähnst ja schon, dass beispielsweise der Stack initialisiert 
wird. Wenn noch kein Stack vorhanden ist, kannst du keine C-Funktionen 
verwenden, da die Parameterübergabe als auch die Rücksprungadresse im 
Stack abgelegt werden bzw. auf den Stack zugreifen.
3. Oft benötigst du spezielle (Assembler)Befehle des Prozessors um z.B. 
Mode-Switches durchzuführen. Das wäre dann inline-Assembler, also warum 
nicht gleich in Assembler.

Es gibt auch Controller bzw. Compilerfamilien, die einen zweistufigen 
Startup-Code nutzen. Das heißt ganz grundlegende Initialisierungen 
werden mit einem Assembler-Modul realisiert und etwas aufwendigere mit 
einem C-Startup-Code Beispielsweise für Variableninitialisierung. IAR 
EWARM ist ein Beispiel.

von hansi (Gast)


Lesenswert?

m.E. nach legt die tool chain, also die linker settings (?), den bereich 
im memory fest, wo der stack liegen soll oder? mit initialisieren meinte 
ich eher pattern reinschreiben. ok war ein dummes beispiel. also im 
konkreten fall wird folgendes gemacht:
-clk settings werden gesetzt
-clk stabilisierungs zeit wird gesetzt
-boot table erstellt

etc..

ich mein im endeffekt werden hier nur system register beschrieben. das 
geht doch auch in c odeR?

von Düsendieb (Gast)


Lesenswert?

Loonix schrieb:
> Antwort passt leider nicht zur Frage (nochmal genau lesen).

Die Antwort stand darüber: >in dem o.g. Fall auf jeden Fall nicht

Der Rest war als Zusatzinfo gedacht.


Axel

von Düsendieb (Gast)


Lesenswert?

hansi schrieb:
> ich mein im endeffekt werden hier nur system register beschrieben. das
> geht doch auch in c odeR?

Das musste in der Regel bei C Programmierung gar nicht selber machen, da 
hat schon der Conpiler dran gedacht.

von Peter D. (peda)


Lesenswert?

Assembler nimmt man, weil genau das ausgeführt wird, was man 
hinschreibt, also in genau der Reihenfolge und in genau der Zeit.
In C ist das nicht so, sondern hängt vom Optimierungslevel und von der 
Compilerversion ab.

Deshalb sind auch Sytembibliotheken (delay.h, wdt.h) nicht in C 
geschrieben, sondern in Inline-Assembler.


Peter

von hansi (Gast)


Lesenswert?

ne eben nicht, das steht ja in meinen start configuration file. gerade 
was die clock settings angeht. denke mal low level hat mit punkt 1 und 3 
schon recht. es ginge in c wäre aber unpassend?!

punkt 2, verstehe ich noch nicht ganz, da ich dachte das der linker 
weiss wo stack liegt und wie groß er ist und eben diesen auch 
verwaltet....

von hansi (Gast)


Lesenswert?

ah ok, also prinzipiell wäre es aber möglich (kein optimierung, etc..)?

von Oliver (Gast)


Lesenswert?

hansi schrieb:
> ah ok, also prinzipiell wäre es aber möglich (kein optimierung, etc..)?

Jein. Solange das C-Environment nicht steht, kannst du C nicht oder nur 
eingeschränkt verwenden. Und alles, was man vor der Erstellung des 
C-Environments ausführen MUSS, geht halt nur in Assembler.

Ob dazu jetzt auch die Einstellung des Taktes oder andere Einstellungen 
am Prozessor selber gehört, hängt von dessen Architektur ab. Bei vielen 
kann man solche Dinge auch am Anfang von main in C machen.

Oliver

von hansi (Gast)


Lesenswert?

Oliver schrieb:
> Jein. Solange das C-Environment nicht steht, kannst du C nicht oder nur
> eingeschränkt verwenden. Und alles, was man vor der Erstellung des
> C-Environments ausführen MUSS, geht halt nur in Assembler.

was genau meinst du mit c environment? was gehört alles dazu?

von Thomas E. (thomase)


Lesenswert?

hansi schrieb:
> wann muss ich explizit auf Assembler zurückgreifen und wann nicht?

Angenommen du willst mit einer einfachen for-Schleife alle Register auf 
0 setzen.

In C wird eines dieser Register als Zähl-Index, ein anderes zur 
Adressierung benutzt. Sowie du das erste dieser beiden Register in 
deiner Schleife überschreibst, beisst sich die Katze in den Schwanz.

Deswegen geht das nur in Assembler.


mfg.

von Peter (Gast)


Lesenswert?

hansi schrieb:
> was genau meinst du mit c environment? was gehört alles dazu?

es düfte schon an Variablen scheitern. Denn die Variabeln liegen 
normlerweise auf dem Stack und der ist ja noch nicht da.

Also du kannst C verwenden nur ohne Funktionen und Variablen.

von Oliver (Gast)


Lesenswert?

Peter schrieb:
> Also du kannst C verwenden nur ohne Funktionen und Variablen.

So ist es.

Die Ausgangsfrage klingt allerdings nach ARM7. Da kannst du im Prinzip 
sofort nach der Stack-Initilisierung eingeschränkt in C loslegen, eben 
mit der Einschränkung, daß noch keinerlei Variablen initilaisiert sind. 
So etwas wie

REGISTER_XY = 0x42;

geht allerdings schon. Takteinstellungen und ähnliches kann man machen, 
wann man will, auch am Anfang von main in C, oder noch viele später.

Oliver

von Düsendieb (Gast)


Lesenswert?

Ich würde mal sagen 100% aller Anfängerprogramme und 80% oder mehr der 
Profianwendungen lassen sich locker in C Programmieren.

Assembler wird hier oft nur wegen des (zweifelhaften) Lerneffekts 
empfohlen

von willibald (Gast)


Lesenswert?

hansi schrieb:
> was genau meinst du mit c environment? was gehört alles dazu?

Initialisierung des Stack
Initialisierung des Heap (falls das Programm malloc/free verwendet)
Initialisierung globaler Variablen

Diese Reihenfolge ist sinnvoll, wenn außer C- auch C++-Programme zur 
Ausführung kommen können, dann braucht man nämlich einen 
funktionstüchtigen Stack (und ggfs. Heap), um globale Objekte zu 
konstruieren.

Werden nur C-Programme unterstützt, dann kann man auch die Variablen 
zuerst erledigen.

Die Einstellung von Hardware-Registern hat hiermit in der Regel (*) 
nichts zu tun und kann prinzipiell gleichermaßen vor oder nach der 
C-Initialisierung geschehen.

(*) Ausnahmen gibt es natürlich, z.B. Setzen des Stackpointers. Oder 
wenn man externen Speicher hat (Heap für größere Datenmengen im externen 
RAM), muss man natürlich, bevor man die C-Runtime den Heap 
initialisieren lässt, den XMem-Controller an den Start bringen. Aber 
selbst das könnte man als primitive C-Routine formulieren und vom 
Assembler-Startupcode aufrufen lassen.

von Oliver (Gast)


Lesenswert?

Düsendieb schrieb:
> Ich würde mal sagen 100% aller Anfängerprogramme und 80% oder mehr der
> Profianwendungen lassen sich locker in C Programmieren.

Thema verfehlt...

Oiver

von Olaf (Gast)


Lesenswert?

> ah ok, also prinzipiell wäre es aber möglich (kein optimierung, etc..)?

Sowas ist moeglich und wird auch durchaus so gemacht.
Allerdings bedarf es unter Umstaenden eines erfahreren C-Programmierer
der mit dem Compiler und Linker gut umgehen kann.

Denn wie schon angedeutet wurde, es sind ein paar Dinge zu beachten:

1. Der Stack muss gesetzt werden.

2. Andere Register muessen eventuell gesetzt werden.
   Ein Beispiel dafuer waeren bei M16C das einstellen der 
Gehaeusegroesse.

3. Die Reihenfolge kann wichtig sein. Auch optimierungslevel des 
Compilers.

4. Die Position im Speicher der Prozessors kann wichtig sein.

5. Es muessen Variable vom Linkerscript oder der Programmierumgebung
   an das C-File uebergeben werden. (z.B Position und groesse des 
Stacks)

6. Man verschenkt beim Aufruf von main() eine Stackposition oder muss
   sich halt einen Sprung einfallen lassen.

> In C wird eines dieser Register als Zähl-Index, ein anderes zur
> Adressierung benutzt. Sowie du das erste dieser beiden Register in
> deiner Schleife überschreibst, beisst sich die Katze in den Schwanz.
>
> Deswegen geht das nur in Assembler.

Nein. Setze einfach als erstes den Stack und verwende dann Variable die 
nur auf dem Stack liegen. Es geht also durchaus in C, allerdings muss 
man trotzdem wie ein Assemblerprogrammierer denken, sich also darueber 
im klaren sein was der Compiler jetzt daraus macht.

Es geht aber noch perverser. :-) So sieht das ganze z.B bei
Renesas aus:

void start(void)
{
  set_cpu();  // initialize mcu

  ram_init();
}

Also ein C-funktion die ihrerseits wieder andere Funktionen aufruft
und zwar ohne das es bis jetzt schon einen Stack gibt.

Und so sieht dann set_cpu aus:

#pragma inline set_cpu()
void set_cpu(void)
{
   isp  = &_istack_top;      // set interrupt stack pointer
  flg  = 0x0080UL;        // set flag register
  sp  = &_stack_top;      // set user stack pointer
  sb  = (_UDWORD *)0x400UL;  // 400H fixation (Do not change)
  _asm("  fset  b");
  sb  = (_UDWORD *)0x400UL;
  _asm("  fclr  b");
  intb = (_UDWORD *)VECTOR_ADR;  // set variable vector's address
}

Das sieht man wieso man erst ohne Stack auskommt. Ausserdem wird 
lustigerweise erstmal doch wieder Assembler benutzt auch wenn es im 
C-Code steht. Ein Problem koennte vielleicht sein das ein anderer 
Compiler
soetwas...

   isp  = &_istack_top;      // set interrupt stack pointer

...uebersetzt indem er einen Zwischenwert auf den Stack speichert.


Olaf

von Düsendieb (Gast)


Lesenswert?

hansi schrieb:
> wann muss ich explizit auf Assembler zurückgreifen und wann nicht?

Das war die Ausgangsfrage.
und ich meine immer noch, wenn man sauber in C programmiert braucht man 
nur aller seltenst auf Assembler zurückgreifen.


Axel

von Peter (Gast)


Lesenswert?

Düsendieb schrieb:
> Das war die Ausgangsfrage.

nein war sie nicht. Es ging im C in start up routinen. Also dem teil vor 
Main. Und mit diesen haben 100% aller Anfängerprogramme überhaupt nicht 
zu tun.

von Düsendieb (Gast)


Lesenswert?

Peter schrieb:
> Und mit diesen haben 100% aller Anfängerprogramme überhaupt nicht
> zu tun.

genau, weil das der Compiler von alleine erledigt

von Oliver (Gast)


Lesenswert?

Düsendieb schrieb:
> genau, weil das der Compiler von alleine erledigt

Eben nicht. Der Compiler erledigt von den Dingen, um die es hier geht, 
überhaupt nichts. Der weiß noch nicht einmal was davon. Für einen 
C-Compiler gibt überhaupt kein Leben vor main(), wohl aber für die 
Hardware.

Alles davor macht der Startupcode, der entweder (für den Anfänger 
versteckt) in der toolchain mitgeliefert und in den ebenfalls 
mitgelieferten linkerscripts berücksichtigt wird, oder eben vom Benutzer 
unabhängig vom Compiler erstellt werden muß.

Oliver

von Düsendieb (Gast)


Lesenswert?

Oliver schrieb:
> (für den Anfänger versteckt)

sag ich doch

von Programist (Gast)


Lesenswert?

Assembler ist halt besser als jeder compiler, weil er direct auf 
hardware zugreift.Compiler übersetzt nur in den assembler, und das tut 
er nicht so gut.Eigentlich hängt das von dem compiler ab, was für den 
code er dann erschaft.Auf jeden Fal ist das nicht so effizient wie 
assembler, das is so als ob du durch einen übersetzer mit jemandem 
sprichst.

von Daniel (Gast)


Lesenswert?

Programist schrieb:
> Assembler ist halt besser als jeder compiler, weil er direct auf
> hardware zugreift.Compiler übersetzt nur in den assembler, und das tut
> er nicht so gut.Eigentlich hängt das von dem compiler ab, was für den
> code er dann erschaft.Auf jeden Fal ist das nicht so effizient wie
> assembler, das is so als ob du durch einen übersetzer mit jemandem
> sprichst.

Alter, bist du ein spacko...

von Benni (Gast)


Lesenswert?

Hallo,

mal eine Frage zu dem Thema... ich habe in ARM7 startup-Routinen schon 
handgeschriebene memcopy Funktionen gesehen, die nur einen 
Speicherbereich mit 0x00, oder sonstigen "Mustern" beschrieben haben zur 
Initialisierung oder Stackverbrauchbestimmung.

Wäre das nicht auch in C vor Runtime-Init programmierbar, solange ich 
keinen Stack verwende und alle Variablen vollständig in den 
Prozessorregistern halten kann?

Gruß

Benni

von Peter (Gast)


Lesenswert?

Benni schrieb:
> solange ich
> keinen Stack verwende und alle Variablen vollständig in den
> Prozessorregistern halten kann?

und wie willst du das machen? (aber bitte ohne irgendwelche C 
erweiterungen)

von Benni (Gast)


Lesenswert?

Naja klar, ohne C pragma oder sonstwas wird da nix laufen, aber im 
Embedded Bereich gehts doch sowieso fast nicht ohne ;)

Ich mein viel hardwarespezifischer kanns ja nichtmehr werden. Ich finde 
nur es wäre leichter zu lesen und überblicken, als eigentlich simple 
Speicherzuweisungen nach Assembler zu packen.

Benni

von Peter (Gast)


Lesenswert?

Benni schrieb:
> ch finde
> nur es wäre leichter zu lesen und überblicken, als eigentlich simple
> Speicherzuweisungen nach Assembler zu packen.

was ist an ASM nicht einfach zu lesen, immer schöne kurze zeilen. Es mir 
lieber als der C code den man hier manchmal sieht.

von Bernd N. (Gast)


Lesenswert?

>> genau, weil das der Compiler von alleine erledigt...

So ist es.

Komische Diskussion, jeder brauchbare C Compiler generiert den 
entsprechenden Startup Code und biete darüber hinaus auch eine 
Möglichkeit diesen zu beeinflußen. Alles andere wäre eine Krücke.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bernd N. schrieb:

> Komische Diskussion, jeder brauchbare C Compiler generiert den
> entsprechenden Startup Code

Nein.  Die meisten Compiler kümmern sich darum überhaupt nicht,
sondern sie überlassen das der Bibliothek und dem Linker.  Wie
schon weiter oben geschrieben wurde: für den Compiler gibt es vor
(und nach) main() keine Welt.

Ob die Laufzeitumgebung nun ihrerseits dafür was mitbringt oder nicht,
scheint von System zu System sehr unterschiedlich gehandhabt zu
werden.  Manche haben das komplett in die Bibliothek integriert,
manche liefern einfach auch nur eine Bausteindatei mit, die man in
sein Projekt mit einbindet und ggf. zusätzlich modifizieren kann.

von Jens A. (micro)


Lesenswert?

Bernd N. schrieb:
>>> genau, weil das der Compiler von alleine erledigt...
>
> So ist es.
>
> Komische Diskussion, jeder brauchbare C Compiler generiert den
> entsprechenden Startup Code und biete darüber hinaus auch eine
> Möglichkeit diesen zu beeinflußen. Alles andere wäre eine Krücke.

Also wenn macht die IDE das eventuell. Der Compiler selber generiert 
garantiert kein Start Up Code.

von Oliver (Gast)


Lesenswert?

Düsendieb schrieb:
> Oliver schrieb:
>> (für den Anfänger versteckt)
>
> sag ich doch

Hier geht es anscheinend um einen ARM, und in dessen toolschains ist das 
schon nicht mehr versteckt, auch nicht für Anfänger. Da kannst (und 
musst) du als Anwender sowohl im startupcode, als auch in den 
linkerscripts selber rumbasteln. Es gibt dazu zwar Beispiele, aber mehr 
nicht.

Und was z.B. auf deinem PC alles passiert, bevor da mal ein main() eines 
von dir geschriebenen Programms loslaufen kann, kannst du ja mal 
versuchen, rauszufinden. Angefangen vom ersten Start des Bios. Viel 
Spaß...

Die Welt besteht nicht nur aus AVR's.

Oliver

von Bernd N. (Gast)


Lesenswert?

ok, ARM kann ich nicht mitreden und ob Compiler oder IDE, Toolchain, 
aknn man natürlich drüber streiten.

Jedenfalls können es die Toolchains mit denen ich arbeite und jede 
bietet die Möglichkeit:
- den StartupCode zu generieren
- den StartupCode zu modifizieren
- den StartupCode zu unterdrücken, respektive selbst zu schreiben

Gibts nen link zu dem Armen ? :-)

von 900ss (900ss)


Lesenswert?

Jörg Wunsch schrieb:
> Ob die Laufzeitumgebung nun ihrerseits dafür was mitbringt oder nicht,
> scheint von System zu System sehr unterschiedlich gehandhabt zu
> werden.

Es scheint nicht so, es ist so :-)

> Manche haben das komplett in die Bibliothek integriert,

Siehe sehr vorbildlich die WinAVR-Toolchain. Das ist tatsächlich
"make & flash & go" ;-) Da weiß die Toolchain, welcher Startupcode 
benötigt wird.

Für ARM gibt es sicher auch soetwas, wenn man eine IDE/Toolchain teuer 
kauft. Da würde ich das zumindest erwarten.

Einen Cortex-M3 kann man in reinem(!) C starten. Habe aber noch nirgends 
gesehen, dass das jemand genutzt hat. Und die erste Funktion die dort 
anläuft ist main(), kein Assemblerbefehl vorher! Dort kann man auf den 
Startupcode in Assembler vollständig verzichten.

Für den SPARC (LEON2, LEON3 von Gaisler) liefert Gaislers freie 
BCC-Toolchain (basiert auf GCC) den Startupcode auch mit. Geht wie bei 
WinAVR, kompilieren, linken und "run". Falls mal jemand mit SPARC 
spielen möchte :-)
Da den Startupcode selber in Assembler schreiben ist schon nicht mehr 
trivial. Und reines C würde auch nicht gehen. Bis man dem die "Fenster 
geputzt" hat.... ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Hier ein konkretes Beispiel, warum Startup-Code idR nur in Assembler 
geschrieben werden kann -- egal ob er mit dem Compiler mitkommt oder bei 
der Generierung von Libs erst mithilfe des Compilers erzeugt wird:

Das ABI von avr-gcc sieht vor, daß in R1 immer der Wert 0 steht. avr-gcc 
geht davon aus, daß dieser Wert in R1 steht. Wie also bekommt man den 
Wert 0 in R1 hinein? Nach dem PowerUp stehen in den Registern R0-R31 
eines AVR zufällige Werte.

Eine Möglichkeit ist Assembler, klar:
1
EOR R1, R1 ; R1 = 0

Wie würde man das in reinem C machen?

Selbt unter Verwendung übelsten Hacks (die AVR-Register werden an die 
RAM-Adressen 0..31 gespiegelt) gelingt das nicht:
1
*((volatile char*) 1) = 0;
wird von avr-gcc nämlich übersetzt als
1
STS 1, R1
denn der Compiler geht davon aus, daß 0 in R1 drinne steht. Also 
speichert er R1 nach 1 ab, um die 0 an Adresse 1 zu bekommen.

Autsch

Daher wird die Quelle des Startup-Code in Assembler geschrieben.

Falls man eigene Funktionen vor main ausgeführt haben will und dazu 
schon eine funktionierende C-Umgebung braucht, dann kann man sich nach 
dem Basis-Startup-Code (also nach Setup von SP, clear-bss, copy-data, 
etc. ) und vor main einklinken mittels GNU-C:
1
static void __attribute__((constructor,used)) 
2
foo (void)
3
{
4
    // ...
5
}

von besucher (Gast)


Lesenswert?

900ss D. schrieb:
> Einen Cortex-M3 kann man in reinem(!) C starten.

Das stimmt. Der CM3-Kern beginnt bei Adresse 0x00000000 und lädt das 
32-Bit-Wort, das er dort findet, in den Stack-Pointer. Damit ist der 
Stack initialisiert.

900ss D. schrieb:
> Und die erste Funktion die dort
> anläuft ist main(), kein Assemblerbefehl vorher! Dort kann man auf den
> Startupcode in Assembler vollständig verzichten.

Das zweite Wort (ab Adresse 0x00000004) wird in den Instruction-Pointer 
geladen. Das kann theoretisch die Adresse von main () sein. In der 
Regel wirds aber ein paar Variablen zu initialisieren geben, und das 
muss laut C-Standard vor dem Eintritt in main erledigt sein. Es wird 
also wahrscheinlich etwas Startup-Code zwischen Reset und main geben 
müssen.

Du hast aber Recht damit, dass dieser STartupcode nicht in Assembler 
geschrieben sein muss.

von Karl M. (movex)


Lesenswert?

Auf einigen Architekturen wie z.B. PowerPC müssen Coreregister geändert 
werden, was nur über eigene Assemblerbefehle (mtspr, mfspr) möglich ist.
Stackpointer, Exeception handling, Timebase, Watchdog, Floating Point 
Unit usw. Die entsprechenden Register liegen nicht im Adressraum.

Abgesehen davon ist dieser Codeteil dann fix und man sucht nicht a der 
Stelle nach Fehlern, wenn am Compiler was nicht stimmt oder eine 
Eisntellung geändert wurde.

von hansi (Gast)


Lesenswert?

OK danke für die zahlreichen antworten. ich denke da sind ein paar gute 
dabei und es ist auch etwas klarer geworden.

was ich aber nicht ganz verstehe ist, wieso der stack explizit in 
assembler initialisiert werden muss.

Stack ist ein bereich im RAM. der linker erstellt doch eine memory map. 
vorher habe ich zB in den settings festgelegt, das addresse 0xabc - 
0xaff im RAM liegen und als stack benutzt werden können. die MCU selbst 
braucht doch nur die start address für den stack pointer 0xaff. nun kann 
die mcu fröhlich pushen und poppen. was genau muss ich da in einer start 
up festlegen? immerhin künmmert sich doch der linker um solche sachen?? 
er legt ja auch das ROM fest für meinen programm code.

danke

p.s. es war kein ARM gemeint :) nehmen wir es eher als allgemein gültige 
frage. wobei der M3 ja zB dann rausfällt wie oben beschrieben.

von willibald (Gast)


Lesenswert?

hansi schrieb:
> was ich aber nicht ganz verstehe ist, wieso der stack explizit in
> assembler initialisiert werden muss.
> ...
> die MCU selbst
> braucht doch nur die start address für den stack pointer 0xaff.

Und wie kommt die Adresse in das Stackpointer-Register hinein? Genau: 
Durch irgendwas wie

        load sp, 0xaff

Normalerweise hast du in C keinen direkten Zugriff auf den Stackpointer. 
Du müsstest Inline-Assembler verwenden, und du müsstest die Funktion so 
kompilieren, dass Vor- und Nachspann den Stackpointer nicht verbiegen 
("attribute naked" oder was es da bei deinem Compiler so für 
Spezialitäten gibt). Auf jeden Fall ist das ein viel größerer Aufriss 
als eine simple Anweisung direkt im Startupcode.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

willibald schrieb:
> Normalerweise hast du in C keinen direkten Zugriff auf den Stackpointer.

Hängt auch wieder von der CPU ab.  Auf dem AVR ist der SP ein normales
IO-Register, das man auch via C erreichen kann.  Überdies kommen
aktuelle AVRs mit einem Reset-Wert im SP daher, der auf das obere
Ende des internen SRAM zeigt, da muss man nur noch was dran ändern,
wenn man den Stack aus irgendeinem Grund woanders haben will.

von hansi (Gast)


Lesenswert?

also besteht das "einrichten" des stacks eingentlich nur aus dem setzten 
des stack pointers?

von willibald (Gast)


Lesenswert?

hansi schrieb:
> also besteht das "einrichten" des stacks eingentlich nur aus dem setzten
> des stack pointers?

Ja. Manchmal wird noch der ganze Stack mit einem Bitmuster vorbelegt, 
was es zur Laufzeit ermöglicht, den "Hochwasserpegel" zu bestimmen oder 
Überläufe zu erkennen.

Aber für die Funktion des Stacks an sich reicht das Setzen des Pointers. 
Und wie Jörg Wunsch schrieb: Manche CPUs brauchen nicht mal das.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

hansi schrieb:
> also besteht das "einrichten" des stacks eingentlich nur aus dem setzten
> des stack pointers?

Das hängt von der Architektur ab. Bei Infineon TriCore zum Beispiel muss 
auf dem Stack-Bereich (CSA, Context Save Area) erst eine verkettete 
Liste aufgebaut werden, welche einzelne Contexte enthält, und der Anfang 
der Liste in ein spezielles Register geschrieben werden -- einmal fürs 
normale Programm, einmal für die Interrupts.

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.