Guten Tag, ich möchte für ein Schulprojekt etwas mit Mikrocontrollern machen und sie auch selbst programmieren. Ein wenig Erfahrung in C-Programmierung habe ich schon. Jetzt bin ich im AVR Studio auf die lss-Datei gestoßen und habe dazu eine Frage. Offensichtlich steht vor meinem eigenem Programm dort noch eine Menge Code: ... 000000e4 <__ctors_end>: e4: 11 24 eor r1, r1 e6: 1f be out 0x3f, r1 ; 63 e8: cf ef ldi r28, 0xFF ; 255 ea: d1 e2 ldi r29, 0x21 ; 33 ec: de bf out 0x3e, r29 ; 62 ee: cd bf out 0x3d, r28 ; 61 f0: 00 e0 ldi r16, 0x00 ; 0 f2: 0c bf out 0x3c, r16 ; 60 000000f4 <__do_copy_data>: f4: 12 e0 ldi r17, 0x02 ; 2 f6: a0 e0 ldi r26, 0x00 ; 0 f8: b2 e0 ldi r27, 0x02 ; 2 fa: e2 ef ldi r30, 0xF2 ; 242 fc: f1 e0 ldi r31, 0x01 ; 1 fe: 00 e0 ldi r16, 0x00 ; 0 100: 0b bf out 0x3b, r16 ; 59 102: 02 c0 rjmp .+4 ; 0x108 <__do_copy_data+0x14> 104: 07 90 elpm r0, Z+ 106: 0d 92 st X+, r0 108: a0 30 cpi r26, 0x00 ; 0 10a: b1 07 cpc r27, r17 10c: d9 f7 brne .-10 ; 0x104 <__do_copy_data+0x10> 0000010e <__do_clear_bss>: 10e: 12 e0 ldi r17, 0x02 ; 2 110: a0 e0 ldi r26, 0x00 ; 0 112: b2 e0 ldi r27, 0x02 ; 2 114: 01 c0 rjmp .+2 ; 0x118 <.do_clear_bss_start> 00000116 <.do_clear_bss_loop>: 116: 1d 92 st X+, r1 00000118 <.do_clear_bss_start>: 118: a0 30 cpi r26, 0x00 ; 0 11a: b1 07 cpc r27, r17 11c: e1 f7 brne .-8 ; 0x116 <.do_clear_bss_loop> 11e: 0e 94 95 00 call 0x12a ; 0x12a <main> 122: 0c 94 f7 00 jmp 0x1ee ; 0x1ee <_exit> 00000126 <__bad_interrupt>: 126: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> ... Was genau passiert da eigentlich? Steht dieser Code eigentlich vor allen Programmen die ich in C schreibe?
Ja. die Interrupttabelle findet sich dort. Stackinitialisierung Variableninitialisierung und der Aufruf der main()
Susann schrieb: > Was genau passiert da eigentlich? __ctors_end stellt den Stapelzeiger ein __do_copy_data kopiert initialte Werte für Variablen vom Flash Speicher ins RAM __do_clear_bss löscht den Speicher aller anderen Variablen. __bad_interrupt Wird für alle Interrupts verwendet, denen du keine eigene Funktion zugewiesen hast. Bei C++ kommt noch ein Block hinzu, der von allen statischen Objekten den Konstruktor aufruft.
Stefanus F. schrieb: > Susann schrieb: >> Was genau passiert da eigentlich? > > __ctors_end stellt den Stapelzeiger ein > > __do_copy_data kopiert initialte Werte für Variablen vom Flash Speicher > ins RAM > > __do_clear_bss löscht den Speicher aller anderen Variablen. > > __bad_interrupt Wird für alle Interrupts verwendet, denen du keine > eigene Funktion zugewiesen hast. > > Bei C++ kommt noch ein Block hinzu, der von allen statischen Objekten > den Konstruktor aufruft. Heißt das, dass alles vorweg auf Null oder so gesetzt wird, ohne dass ich dafür in meinem Programm etwas tun muß?
Susann schrieb: > Heißt das, dass alles vorweg auf Null oder so gesetzt wird, ohne dass > ich dafür in meinem Programm etwas tun muß? In C (und C++) werden alle globalen und statischen Variablen mit Integer-Typ, welche nicht explizit initialisiert sind, auf 0 gesetzt. Dies ist vom Standard gefordert und wird hier eben von der avr-libc durch eine Schleife so umgesetzt. Das heißt, dass du globale/statische Variablen nicht auf 0 setzen musst. Lokale nicht-statische Variablen werden allerdings standardmäßig gar nicht initialisiert, da musst du immer einen Wert vorgeben.
1 | int foo; // Wird auf 0 gesetzt |
2 | int foo = 0; // Wird auf 0 gesetzt |
3 | int bar = 42; // Wird auf 42 gesetzt |
4 | |
5 | int main () { |
6 | int blub = 21; // Wird auf 21 gesetzt |
7 | static int blar = 77; // Wird auf 77 gesetzt |
8 | static int fasel; // Wird auf 0 gesetzt |
9 | int blab; // Wird nicht initialisiert - es muss vor dem ersten Lesen ein Wert zugewiesen werden! |
10 | }
|
Die Konstruktoren von C++-Objekten werden allerdings immer aufgerufen (außer in unions).
Susann schrieb: > Heißt das, dass alles vorweg auf Null oder so gesetzt wird, ohne dass > ich dafür in meinem Programm etwas tun muß? Jein. Globale Variablen sind 0, wenn du keinen anderen Startwert vorgibst:
1 | #include <avr/io.h> |
2 | |
3 | int i; |
4 | int j=3; |
5 | |
6 | int main() |
7 | {
|
8 | int k; |
9 | printf("i=%d j=%d k=%d", i,j,k); |
10 | }
|
i Startet mit dem Wert 0. j Startet wird dem Wert 3 (der Startwert wird aus dem Flash kopiert). k Hat keinen definierten Startwert, da kann ein Zufallswert drin stehen. Merke: Globale Variablen werden immer mit 0 oder einem angegebenen Startwert initialisiert. Lokale Variablen werden hingegen nur dann initialisiert, wenn du es ausdrücklich hin schreibt. Noch eine Kleinigkeit: Variablen in Funktionen werden durch denn Code der Funktion bei jedem Aufruf initialisiert. Es sei denn, da steht das Schlüsselwort "static" vor, denn dann ist es technisch gesehen eine globale Variable, die allerdings nur innerhalb der Funktion genutzt werden darf. Nachtrag: Niklas hat mich überholt. > In C (und C++) werden alle globalen und statischen Variablen mit > Integer-Typ, welche nicht explizit initialisiert sind, auf 0 gesetzt. Ich glaube, das trifft sogar auf alle Typen zu, nicht nur Integer.
Stefanus F. schrieb: > Ich glaube, das trifft sogar auf alle Typen zu, nicht nur Integer. wieso glaubst du, ich denke du bist Informatiker und nicht Kleriker? Was ist mit Pointer? Im Zweifel lieber initialisieren!
Joachim B. schrieb: > Was ist mit Pointer? > > Im Zweifel lieber initialisieren! Ich als Informatiker habe meine überlegenen Google-Skills genutzt um es nachzuschauen: https://en.cppreference.com/w/cpp/language/zero_initialization "A zero-initialized pointer is the null pointer value of its type, even if the value of the null pointer is not integral zero." Zeiger werden automatisch also als Null-Zeiger initialisiert. Die manuelle Initialisierung ist also unnötig.
Niklas G. schrieb: > A zero-initialized pointer is hmmm, Juristendenglish? ist der "zero-initialized pointer" nun mit zero initialisiert oder ist er uninitialisiert? ich bleibe dabei, wer sicher sein will Joachim B. schrieb: > Im Zweifel lieber SELBER initialisieren!
Joachim B. schrieb: > hmmm, Juristendenglish? Sprachstandards sind ziemliches Juristenenglisch, ja - sie müssen schließlich präzise sein. Joachim B. schrieb: > ich bleibe dabei, wer sicher sein will Es ist trotzdem unnötig. Im C++ Standard (N4659 Draft) heißt es in Kap 11.6: To zero-initialize an object [...] of type T means: (6.1) — if T is a scalar type (6.9), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T - 104 In Fußnote 104: 104) As specified in 7.11, converting an integer literal whose value is 0 to a pointer type results in a null pointer value. In Kapitel 6.9: [...] pointer types, pointer to member types (6.9.2), std::nullptr_- t, and cv-qualified (6.9.3) versions of these types are collectively called scalar types. Joachim B. schrieb: > ist der "zero-initialized pointer" nun mit zero initialisiert Ja.
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.