ZIEMLICH DIRTY. sprung auf einen pointer in c?

dettus

Bicycle User
hi!

hat jemand von euch eine idee, wie ich unter c einen unterprogrammaufruf an eine ganz bestimmt stelle im speicher hinkriege?

mein problem hier ist, dass ich gerade den bootloader von einem embedded device hacken muss, und fuer einen kurzen programmteil muss ich vom flash-rom auf den sram umschalten.
dazu schreibe ich erstmal die kommandos, die ich brauche ins sram, per
Code:
((*volatile int) 0x04000000)=0xef9018ff;
((*volatile int) 0x04000004)=0x00000414;
usw.

dann sollte irgendwie ein
Code:
JSR 0x04000000
kommen. wo der dann an die erste adresse springt...

hat irgendwer ne idee?
 
inline Assembler oder Funktionszeiger.
Musst allerdings darauf achten, dass du nichts dabei kaputt machst, ergo Funktionsprolog und -epilog richtig implementierst und Registerinhalte bewahrst.
Übrigens fehlen in den beiden Zuweisungen je ein *.
 
Mal geraten... Kann man einem Funktionspointer nicht eine Adresse zuweisen? Eigentlich macht man ja nichts anderes, wenn man einen Funktionspointer an eine Funktion uebergibt.

HTH
 
Auch wenn Du's schon gelöst hast... aber was Du da gepostet hast ja sehr hässlich ;)

dettus schrieb:
Code:
((*volatile int) 0x04000000)=0xef9018ff;
((*volatile int) 0x04000004)=0x00000414;

(...)

Code:
JSR 0x04000000

Der Teil hier ist extrem dreckig und unwartbar. Spontan fallen mir zwei Möglichkeiten ein das wesentlich sauberer und wartbarer zu lösen.

Zunächst schreibst Du Dir die Funktion in Assembler, nicht inline sondern als separate Datei. Am Anfang und am Ende des Codes definierst Du Dir ein Label. Hier mal eine NOP Funktion in PowerPC-Assembler wie sie unter Mac OS X funktioniert:

Code:
.text
    .globl _init_start
    .globl _init_end
_init_start:
    stw r0, 4(r1)
    stwu r1, -64(r1)
    lwz r1, 0(r1)
    blr
_init_end:

Dieser Code wird nun ins Binary-File gelinkt. Bis hier hin unterscheiden sich die beiden Möglichkeiten nicht. Ok, das _init_end Label brauchst Du bei der ersten Möglichkeit nicht...

Nun gehst Du her und weist den Linker an, eben dieses Stück Code schon an 0x4000000 zu linken. Das ist sicher am saubersten, aber ich habe (aus dem Kopf) keine Ahnung wie das Linker-Script aussehen muss.

Die zweite Möglichkeit ist etwas einfacher:

Code:
void init_start();
void init_end();

int
main(int argc, char **argv) {
    void (*init)(void) = 0x4000000;

    memcpy(init, &init_start, &init_end - &init_start);

    init();
}

Du kopierst einfach zur Laufzeit den Code an die richtige Stelle und verzweigst dann per Funktionszeiger dahin. Die Sache mit dem Funktionszeiger ist so üblich... ;)
 
Zurück
Oben