mikrocontroller.net

Forum: Compiler & IDEs AVR-GCC Code nach Adresse 0x0000


Autor: Anton Wert (antonwert)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schreibe schon länger Programme für diverse AVRs mit dem GCC. Nun frage
ich mich aber was der für einen Code erzeugt welcher vor main
aufgerufen wird.
Habe hierzu testweise ein Programm erzeugt was eigentlich nix macht
g. Einiges ist mir klar - doch vieles auch unbegreiflich. Vielleicht
weis ja jemand was hier passiert:
Mich interressier besonders das ab Adresse 1B


--> Hier beginnt die Interrupt Vektor Table
+00000000:   C014        RJMP    PC+0x0015        Relative jump
+00000001:   C02D        RJMP    PC+0x002E        Relative jump
+00000002:   C02C        RJMP    PC+0x002D        Relative jump
+00000003:   C02B        RJMP    PC+0x002C        Relative jump
+00000004:   C02A        RJMP    PC+0x002B        Relative jump
+00000005:   C029        RJMP    PC+0x002A        Relative jump
+00000006:   C028        RJMP    PC+0x0029        Relative jump
+00000007:   C027        RJMP    PC+0x0028        Relative jump
+00000008:   C026        RJMP    PC+0x0027        Relative jump
+00000009:   C025        RJMP    PC+0x0026        Relative jump
+0000000A:   C024        RJMP    PC+0x0025        Relative jump
+0000000B:   C023        RJMP    PC+0x0024        Relative jump
+0000000C:   C022        RJMP    PC+0x0023        Relative jump
+0000000D:   C021        RJMP    PC+0x0022        Relative jump
+0000000E:   C020        RJMP    PC+0x0021        Relative jump
+0000000F:   C01F        RJMP    PC+0x0020        Relative jump
+00000010:   C01E        RJMP    PC+0x001F        Relative jump
+00000011:   C01D        RJMP    PC+0x001E        Relative jump
+00000012:   C01C        RJMP    PC+0x001D        Relative jump
+00000013:   C01B        RJMP    PC+0x001C        Relative jump
+00000014:   C01A        RJMP    PC+0x001B        Relative jump
--> Hier endet die Interrupt Vektor Table
--> Hier wird das Status Register gelöscht, aber warum??
+00000015:   2411        CLR     R1               Clear Register
+00000016:   BE1F        OUT     0x3F,R1          Out to I/O location
--> Er setzt den Stack-Pointer, OK!
+00000017:   E5CF        LDI     R28,0x5F         Load immediate
+00000018:   E0D2        LDI     R29,0x02         Load immediate
+00000019:   BFDE        OUT     0x3E,R29         Out to I/O location
+0000001A:   BFCD        OUT     0x3D,R28         Out to I/O location
--> und das folgende ist mir total schleierhaft....
+0000001B:   E010        LDI     R17,0x00         Load immediate
+0000001C:   E6A0        LDI     R26,0x60         Load immediate
+0000001D:   E0B0        LDI     R27,0x00         Load immediate
+0000001E:   E6EC        LDI     R30,0x6C         Load immediate
+0000001F:   E0F0        LDI     R31,0x00         Load immediate
+00000020:   C002        RJMP    PC+0x0003        Relative jump
+00000021:   9005        LPM     R0,Z+            Load program memory
and postincrement
+00000022:   920D        ST      X+,R0            Store indirect and
postincrement
+00000023:   36A0        CPI     R26,0x60         Compare with
immediate
+00000024:   07B1        CPC     R27,R17          Compare with carry
+00000025:   F7D9        BRNE    PC-0x04          Branch if not equal
+00000026:   E010        LDI     R17,0x00         Load immediate
+00000027:   E6A0        LDI     R26,0x60         Load immediate
+00000028:   E0B0        LDI     R27,0x00         Load immediate
+00000029:   C001        RJMP    PC+0x0002        Relative jump
+0000002A:   921D        ST      X+,R1            Store indirect and
postincrement
+0000002B:   36A0        CPI     R26,0x60         Compare with
immediate
+0000002C:   07B1        CPC     R27,R17          Compare with carry
+0000002D:   F7E1        BRNE    PC-0x03          Branch if not equal
--> Dies ist der Jump nach main!
+0000002E:   C001        RJMP    PC+0x0002        Relative jump
+0000002F:   CFD0        RJMP    PC-0x002F        Relative jump
@00000030: main

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist der sogenannte "startup-Code", der den Prozessor soweit
initialisiert, daß main aufgerufen werden kann. Wie Du schon
herausgefunden hast, initialisiert das beispielsweise den Stack und die
Interrupttabelle.

Der Quelltext dieses Startupcodes sollte beim Compiler eigentlich dabei
sein; da ich gcc nicht einsetze, kann ich Dir da leider keine genaueren
Hinweise geben.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Quelltext dafür ist bei der avr-libc mit dabei.  Natürlich
nur, wenn man sich den Sourcecode mit installiert.

Autor: Anton Wert (antonwert)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg Wunsch
OK, aber wo...? Sind für eine zufällige Suche einfach zuviele Dateien

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe eine Vollinstallation gemacht, finde bei mir aber keine einzige
 C Datei im WinAVR Ordner...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Sourcecode gibt's separat, ansonsten wäre WinAVR ja noch
x-mal größer als es sowieso schon ist.

Meiner Erinnerung nach hat Eric im README auch beschrieben, wo's
den gibt.  Für avr-libc:

http://download.savannah.nongnu.org/releases/avr-l...

Keine Angst vor .tar.bz2, erstens kann man das mit dem
mitgelieferten tar-Kommando auspacken:

tar -xvj -f avr-libc-1.4.3.tar.bz2

und außerdem sollten auch aktuelle WinZips das können.  Die
fragliche Datei heißt crt1/gcrt1.S.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um code vor "main()" aufzurufen, braucht er den Quelltext der lib
nicht anfassen, das ist schon eingebaut.

Schau mal hier:
http://www.nongnu.org/avr-libc/user-manual/mem_sections.html

Abschnitt über ".initN" sections.

Die werden sequenziell abgearbeitet, code in der init1 section z.B.
bereits bevor der Stack initialisiert wurde.

also einfach in den C code eine funktion mit attribute "naked" und
"section .init1" anlegen, den Rest erledigt der Linker.

/Ernst

Autor: Anton Wert (antonwert)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe mir eben die "gcrt1.S" angeschaut.
Glaube sogar meine Stackpointer inizialisierungs-Routine gefunden
wiedergefunden zu haben, nur was der Code macht, bzw. was sonst in der
Datei steht ist mir immernoch ein Rätsel. Kann das jemand mit eigenen
Worten "beschreiben" was da geschieht?

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der grossteil ist:

- init stack
- init zero_reg (register mit 0 vorbelegen)

- Kopieren von Flash->RAM um vorinitialisierte Variablen zu belegen,
also sachen wie:

unit16_t xxx=123;
char * string="Hallo Welt";

usw.

- Löschen (füllen mit 0x00) von Speicherbereichen mit unititialisierten
Variablen

- default Interrupt-Handler deklarieren, der einen Reset auslöst.

Bei C++ kommt dann noch Code für Konstruktoren von globalen Objekten
hinzu.

/Ernst

Autor: Anton Wert (antonwert)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na der Beitrag von Ernst war mal ein Anfang in die Richtige Richtung
-Danke.

Nur ich frage mich immernoch wozu, denn mein Beispielprogramm
beinhaltet ja praktisch nichts ausser Main also auch keine Variablen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Nur ich frage mich immernoch wozu, denn mein Beispielprogramm
> beinhaltet ja praktisch nichts ausser Main also auch keine
> Variablen.

Die Initialisierungsfunktionen sind mehr theoretisch optional.
Praktisch generiert der Compiler stets ungelöste Referenzen auf diese
Funktionen, sodass der Linker sie immer mit einbindet.  Das ist wohl
mal 'ne Idee von Marek Michalkiewicz gewesen, dass der Compiler das
tatsächlich feststellt, was gebraucht wird, die aber nie wirklich zu
Ende gebaut worden ist.

Für die meisten ,,richtigen'' Programme ist es eher belanglos, da
sie
in irgendeiner Form natürlich Variablen benutzen. ;-)  Am ehesten
passiert es noch, dass jemand keinerlei initialisierte Variablen
braucht und daher diese Funktion weggelassen werden könnte.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.