Forum: Mikrocontroller und Digitale Elektronik asm indirekte Addresse zuweisen


von pegel (Gast)


Lesenswert?

Es ist vielleicht in dem alten Beitrag untergegangen, aber nach dem ich 
alle Möglichkeiten die mir eingefallen sind durch habe, probiere ich es 
aus Verzweiflung hier noch mal.

{__asm__ (" LedOn            = 0x0801001D ...

LedOn ist eine Funktion, die an Adresse 0x0801001D liegt.
Die Adresse liegt auch auch indirekt im Speicher 0x08010000.
Ich möchte diese Adresse der Funktion indirekt aus dem Speicher 
zuweisen.
Also in etwa so:

{__asm__ (" LedOn            = [0x08010000] ... //dort steht 0x0801001D

Funktioniert so aber nicht.
Gibt es hier einen asm Profi, der mir zeigt, wie es richtig gemacht 
wird?
Ist für STM32, sollte aber für alle ARM unter GCC gleich sein.

Danke schon mal.

von Oliver S. (oliverso)


Lesenswert?

Hä?

pegel schrieb:
> LedOn ist eine Funktion, die an Adresse 0x0801001D liegt.

Ok.

> Die Adresse liegt auch auch indirekt im Speicher 0x08010000.
> Ich möchte diese Adresse der Funktion indirekt aus dem Speicher
> zuweisen.
> Also in etwa so:
>
> {__asm__ (" LedOn            = [0x08010000] ... //dort steht 0x0801001D
>
> Funktioniert so aber nicht.

Was soll da auch funktionieren? Die Funktion liegt da, wo sie liegt, an 
Adresse 0x0801001D. Der kannst und sollst und willst du nichts zuweisen. 
Warum auch, die liegt doch schon da, wo du die haben willst.

Was also willst du wirklich erreichen?

Oliver

: Bearbeitet durch User
von pegel (Gast)


Lesenswert?

Doch, passt schon. Es geht um BluePill Funktionen in den oberen 64k, die 
fest sind und von vielen Projekten genutzt werden.

von pegel (Gast)


Lesenswert?

Na gut, hätte schreiben sollen:
Funktionsname -> Addresszuweisung

von Oliver S. (oliverso)


Lesenswert?

Und was hat das mit deiner Frage zu tun? Die ist nach wie vor völlig 
abstrus und wirr.

Um mal eine zu beantworten: der Compiler kann keine Speicherstellen 
auslesen.

Oliver

von PittyJ (Gast)


Lesenswert?

Warum ist das so wichtig, wo die Funktion liegt?
Darum kümmere ich mich nie, das macht der Linker.

Kann man auch wunderbar mit dem C/C++ Mitteln bekommen.
https://www.c-plusplus.net/forum/topic/301522/adresse-funktion-ausgeben

und mit C kann man diesen Wert auch wunderbar überall in den Speicher 
schreiben.
Wozu noch dieses asm-Inline gefrickel?

von Axel S. (a-za-z0-9)


Lesenswert?

pegel schrieb:
> Doch, passt schon. Es geht um BluePill Funktionen in den oberen 64k, die
> fest sind und von vielen Projekten genutzt werden.

Gibt auch keinen Sinn IMHO. Bei ARM ist nichts magisches an der 64K 
Grenze. Funktionspointer sind 32 Bit lang. Funktionspointer sind auch zu 
int castbar. Und dann in ein Array von int speicherbar. Falls ich das 
jetzt richtig verstanden habe und du eine Menge von Funktionen in Form 
einer Vektortabelle verfügbar machen willst.

von pegel (Gast)


Lesenswert?

Wie gesagt, ein neues Projekt soll ihm unbekannte Funktionen aus den 
oberen 64k kennen lernen und benutzen.
BluePill ist nur der Test. Andere externe Speicher kommen später dazu.

Es geht wirklich nur um die Adresszuweisung um Handarbeit zu sparen.
Es funktioniert ja schon.

von (prx) A. K. (prx)


Lesenswert?

pegel schrieb:
> Ist für STM32, sollte aber für alle ARM unter GCC gleich sein.

typedef uint32_t LedOn_t (uint32_t arg1); // function prototype
LedOn_t LedOn = (LedOn_T) 0x0801001D;

von Oliver S. (oliverso)


Lesenswert?

Aha. Wenn du noch mehr Salamischeiben hast, kannst du die bitte am Stück 
servieren?

Oliver S. schrieb:
> Was also willst du wirklich erreichen?

Oliver

von (prx) A. K. (prx)


Lesenswert?

(prx) A. K. schrieb:
> pegel schrieb:
>> Ist für STM32, sollte aber für alle ARM unter GCC gleich sein.
>
> typedef uint32_t LedOn_t (uint32_t arg1); // function prototype
> LedOn_t LedOn = (LedOn_T) 0x0801001D;

Clipboard-Fehler. Korrekt:
1
typedef uint32_t LedOn_t (uint32_t arg1); // function prototype
2
LedOn_t *LedOn = (LedOn_t *) 0x0801001D;
3
4
LedOn(1):

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

(prx) A. K. schrieb:

> // function prototype

Ich bin praktisch sicher: Von sowas hat der TO noch nie was gehört...

von Nils (Gast)


Lesenswert?

Da gibt es einen Trick bein GCC:

Du kannst im Assembler ein globales Label definieren, und dann einen 
Function Protype mit dem gleichen Namen definieren.

Beispiel:
1
asm (".globl myCrazyFunc");
2
asm ("myCrazyFunc = 0x1234567");
3
4
extern "C" void myCrazyFunc (int a, int b);

Definiert eine Funktion mit dem im Prototype angegebenen Parametern, die 
der Linker dann auf einen Aufruf an die Adresse 0x1234567 auflöst.

Wenn Du mit C programmierst, dann kannst Du das "extern C" natürlich 
weglassen.

Ich denke, das ist genau das, was Du gesucht hast.

Gruß,
  Nils

von pegel (Gast)


Lesenswert?

Ja, ihr habt Recht. Es fehlt mir an Wissen.
Deshalb würde ich gern einfach diesen asm Befehl wissen.

von pegel (Gast)


Lesenswert?

@ Nils
so genau mache ich das auch.
Nur will ich nicht 0x1234567 eingeben, sondern die Adresse wo die 
0x1234567 drin steht.

von Oliver S. (oliverso)


Lesenswert?

Es gibt schlicht keinen asm-„Befehl“, der das tut, was du möchtest. Du 
kannst einem Label (was anderes ist ein Funktionsname nicht) nur direkt 
einen Wert zuweisen, so, wie es in den Beispielen zuvor gemacht wurde. 
Eine indirekte Zuweisung „hole den Wert dazu aus einer Speicherstelle“ 
gibt es auf dieser Sprachebene nicht.

Es gibt im Befehlssatz des Prozessors Befehle für indirekte Sprünge. 
Guggst du Befehlsreferenz…

Die musst du dann passend mit anderen in der richtigen Reihenfolge 
hintereinander schreiben, um das zu erreichen, was du möchtest. Das 
nennt man dann landläufig „Programm“.

Oliver

: Bearbeitet durch User
von Nils (Gast)


Lesenswert?

Probier dies mal aus:

Einfach in's C File reinhauen:
1
asm (".globl LedOn");
2
asm ("LedOn = 0x0801001D");
3
void LedOn (void);

Und dann in Main:

z.B:
1
void main (void)
2
{
3
  LedOn();
4
}

Wie gesagt, bei C++ braucht es noch ein "extern C" in der 
Funktionsdeklaration. Wenn das funktioniert (ich hab es nicht getestet, 
aber es kompiliert und linkt sauber durch) dann kannst Du den oberen 
Code Teil mit der Deklaration und dem festnageln der Funktion auf eine 
feste Adresse in ein  Header File schreiben und überall in Deinem 
Projekt benutzen.

Gruß,
  Nils

von Nils (Gast)


Lesenswert?

pegel schrieb:
> so genau mache ich das auch.
> Nur will ich nicht 0x1234567 eingeben, sondern die Adresse wo die
> 0x1234567 drin steht.

Das geht leider nicht. So schlau ist der GCC Linker nicht. Sorry.

von pegel (Gast)


Lesenswert?

Oliver S. schrieb:
> Eine indirekte Zuweisung „hole den Wert dazu aus einer Speicherstelle“
> gibt es auf dieser Sprachebene nicht.

Das ist doch mal ein Wort.
Also werde ich einfach eine Adressen Tabelle mit fester Größe an den 
Anfang des Bereiches legen und bei Bedarf neue Funktionen der Reihe nach 
einfügen.
Dann bleiben alte Funktionsadressen erhalten und müssen nur einmal per 
Hand eingetragen werden.

Problem gelöst!

von pegel (Gast)


Lesenswert?

@ Nils
Danke für die Bestätigung.

von Axel S. (a-za-z0-9)


Lesenswert?

pegel schrieb:
> Oliver S. schrieb:
>> Eine indirekte Zuweisung „hole den Wert dazu aus einer Speicherstelle“
>> gibt es auf dieser Sprachebene nicht.
>
> Das ist doch mal ein Wort.

Ein falsches Wort.
1
void* table[10] = 0x0800ABCD; //10 Funktionen
2
3
// die dritte ist die LedOn() Funktion
4
typedef uint32_t LedOn_t (uint32_t arg1); 
5
LedOn_t *LedOn = (LedOn_t *)(table[2]);
6
7
LedOn(1)

> Also werde ich einfach eine Adressen Tabelle mit fester Größe an den
> Anfang des Bereiches legen und bei Bedarf neue Funktionen der Reihe
> nach einfügen.
> Dann bleiben alte Funktionsadressen erhalten und müssen nur einmal per
> Hand eingetragen werden.

Bringt nur überhaupt nichts. Die Prototypen der Funktionen müssen 
ohenhin bekannt sein. Es sei denn, sie haben alle den gleichen. Aber 
wenn du die Prototypen im eigentlichen Zielprogramm kennen mußt, dann 
kannst du auch die Adressen der Funktionen dort eintragen. Wenn du nur 
Funktionen hinzufügst, ändern sich die alten Adressen auch nicht.

> Problem gelöst!

Welches "Problem" auch immer

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.