www.mikrocontroller.net

Forum: Compiler & IDEs Funktion an bekannter (konstanter) Adresse aufrufen


Autor: speedy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Übersetzen dieses Programmes

#include <avr/io.h>

const void (*foo)(void) =0;

int main(void)
{
  foo();
  return 0;
}

erzeugt folgenden code:

0000005c <main>:
  5c:  cf e5         ldi  r28, 0x5F  ; 95
  5e:  d4 e0         ldi  r29, 0x04  ; 4
  60:  de bf         out  0x3e, r29  ; 62
  62:  cd bf         out  0x3d, r28  ; 61
  64:  e0 91 60 00   lds  r30, 0x0060
  68:  f0 91 61 00   lds  r31, 0x0061
  6c:  09 95         icall
  6e:  80 e0         ldi  r24, 0x00  ; 0
  70:  90 e0         ldi  r25, 0x00  ; 0
  72:  00 c0         rjmp  .+0        ; 0x74

ich hätte aber erwartet, dass bei den Adressen 64..6d
folgendes steht:

  64:  e0 91 00 00   lds  r30, 0x0000
  68:  f0 91 00 00   lds  r31, 0x0000
  6c:  09 95         icall

Warum ist das nicht so ??? Ich möchte erreichen, dass
ich eine Funktion an einer bekannten Adresse ausführen kann.
Damit will ich erreichen, dass ich Code der sich im Bootloader
eines ATmega befindet auch im Anwenderprogramm nutzen kann.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fragen, warum der gcc etwas genau so, und nicht anders macht, sind 
selten sinnvoll zu benatworten. Aber in den allermeisten Fällen 
funktioniert das :-)

const void (*foo)(void) =0; legt einen Datenbereich für einen Pointer 
auf eine Funktion an. Der liegt, aus Gründen unerfindlicher Weisheit von 
Compiler und Linker, an den Adressen 0x060 und 0x061 im Datenspeicher, 
und wird mit an Sicherheit grenzender Wahrscheinlichkeit vor dem Aufruf 
der Funktion main() mit dem Wert 0x0000 initialisiert. (sollte sich im 
Code finden lassen)

lds  r30, 0x0060 lädt den INHALT von Datenadresse 0x60, also 0x00.

Oliver

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube, Oliver hat recht.
Ich möchte eine Variable an eine bestimmte Stelle im RAM setzen, und 
verwende eine ähnliche Syntax. Nach begutachten des ASM-Codes steht aus 
sowas da wie:

Lade Z-Pointer mit var aus ram
greife auf Z-Pointer zu..

diese "var aus ram" beinhaltet genau meine gewünschte speicherzelle.

Bei dir ist genau dasselbe passiert:
Der Compiler speichert deine Adresse 0x0000 auf 0x60/0x61 und lädt das 
dann ins Z-Register zur Weiterverwendung..
Warum er hier nicht das Z-Register direkt lädt, weiß ich auch nicht...

Hier der Topic:
Beitrag "variable im externen RAM"

Autor: speedy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Erklärungen. Ich habe LDS mit LDI verwechselt ;)
Nach nochmaligem nachschauen im Datenblatt der MCU ist auch klar,
warum die Adressen 0x60 und 0x61 verwendet werden. Dort beginnt der RAM
Bereich die Adressen 0x00 bis 0x5f sind von Regisetern und IO Adressen
belegt. Ich habe irgendwie erwartet, der GCC sieht den Zeiger auf die
Funktion foo() als Konstante an. Aber ist schon richtig. Warum sollte
er das tun.


Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es ist eine globale Variable. Die landen eher nicht in Registern.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach, noch eine Frage: Warum definierst du foo als Zeiger auf eine 
Funktion, die ein "const void" zurückgibt?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du eine Konstante dafür haben willst, solltest du es dem Linker
überlassen.

Ich habe aus einem anderen Anlass neulich das beigefügte Beispiel mal
geschrieben.  Das implementiert eine "shared library", also einen
Zugriff auf vorgelinkte Funktionen an einer festen Stelle im ROM.  Das
ist sehr ähnlich zu deinem Problem (außer dass du noch einen
Resetvektor für den Bootload in der Sprungtabelle ganz am Anfang
brauchst), und sollte sich einfach anpassen lassen.

Autor: speedy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Ach, noch eine Frage: Warum definierst du foo als Zeiger auf eine
>> Funktion, die ein "const void" zurückgibt?

Hallo Rolf, der Rückgabewert const void der Funktion war der vergebliche
Versuch einen Konstanten Zeiger auf ein Funktion zu definieren.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Hallo Rolf, der Rückgabewert const void der Funktion war der
> vergebliche Versuch einen Konstanten Zeiger auf ein Funktion zu
> definieren.

Um anzuzeigen, dass foo konstant ist, muss das const for dem foo,
nicht vor dem Rückgabetyp stehen:

  void (*const foo)(void) =0;

Wenn du dann noch die Optimierungsstufe -O2 wählst, kommt auch der
erwartetet Code heraus:

  52:  cf e5         ldi  r28, 0x5F  ; 95
  54:  d2 e0         ldi  r29, 0x02  ; 2
  56:  de bf         out  0x3e, r29  ; 62
  58:  cd bf         out  0x3d, r28  ; 61
  5a:  e0 e0         ldi  r30, 0x00  ; 0
  5c:  f0 e0         ldi  r31, 0x00  ; 0
  5e:  09 95         icall
  60:  80 e0         ldi  r24, 0x00  ; 0
  62:  90 e0         ldi  r25, 0x00  ; 0
  64:  00 c0         rjmp  .+0        ; 0x66 <_exit>

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.