Forum: Mikrocontroller und Digitale Elektronik Frage zu AVR-Datei


von Susann (Gast)


Lesenswert?

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?

von Karl B. (gustav)


Lesenswert?

Hi,
hierzu gab es einen älteren Thread:

Beitrag "Interpretation AVR-GCC *.lss File"

ciao
gustav

von Ike (Gast)


Lesenswert?

Ja.

die Interrupttabelle findet sich dort.
Stackinitialisierung
Variableninitialisierung
und der Aufruf der main()

von Stefan F. (Gast)


Lesenswert?

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.

von Susann (Gast)


Lesenswert?

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ß?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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

von Stefan F. (Gast)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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!

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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!

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.