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.
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
Doch, passt schon. Es geht um BluePill Funktionen in den oberen 64k, die fest sind und von vielen Projekten genutzt werden.
Na gut, hätte schreiben sollen: Funktionsname -> Addresszuweisung
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
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?
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.
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.
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;
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
(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
(prx) A. K. schrieb: > // function prototype Ich bin praktisch sicher: Von sowas hat der TO noch nie was gehört...
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
Ja, ihr habt Recht. Es fehlt mir an Wissen. Deshalb würde ich gern einfach diesen asm Befehl wissen.
@ Nils so genau mache ich das auch. Nur will ich nicht 0x1234567 eingeben, sondern die Adresse wo die 0x1234567 drin steht.
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
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
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.
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!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.