www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Absolute Funktionsadressen in Tabelle ablegen


Autor: A.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

Ich benötige in meinem Design eine Tabelle mit den absoluten Adressen 
von mehreren Funktionen. Die Tabelle selbst soll konstant sein und wird 
im ROM abgelegt.

Beispiel:

funcA() // Funktion liegt z.B. auf 0x1000 im ROM
funcB() // Funktion liegt z.B. auf 0x2001 im ROM


const unsigned char table [][] = {{0x10, 0x00};
                                  {0x20, 0x01};

Ich würde nun die Tabelle gerne folgendermaßen anlegen:

const unsigned char table [][] = {{&funcA + 1, &funcA},
                                  {&funcB + 1, &funcB};

Das "+ 1" soll das high - byte der adresse darstellen (ist mir schon 
klar dass sich obiges nicht übersetzen lässt).

Da sich die Adressen nach jedem Linker - vorgang ändern würde ich schon 
gern irgendwelche Makros oder #defines verwenden und die Funktionen 
nicht auf feste adressen legen.

Ich habs schon versucht wenn ich den daten - typen der tabelle weglasse, 
aber das ist nicht akzeptabel.
const table [][] = {{&funcA}, {&funcB};


Kennt jemand eine brauchbare oder ähnliche lösung?

PS: Ich verwende Keil und einen 80C51.

lg. _AS

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erzähl dochmal, was das werden soll.

Klingt stark nach Sackgasse.

Du kannst nicht erwarten, wenn Du 2 verschiedene Programme schreibst, 
daß die sich gegenseitig aufrufen können ohne zu crashen. Denn das eine 
kennt nicht die SRAM-Benutzung des anderen.

Wenn es aber nur ein Programm ist, dann interessiert keine Sau die 
absolute Adresse, denn der Linker löst alles auf.


Peter


P.S.:
Wer arbeitet denn heutzutage noch mit ROM ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Kennt jemand eine brauchbare oder ähnliche lösung?

Jedes C-Buch kennt eine: Funktionszeiger.

Falls du kein C-Buch hast, kannst du alternativ auch mit
der Kurzfassung vorlieb nehmen (*)
http://www.mikrocontroller.net/articles/FAQ#Funktionszeiger


(*) und dir dann anschliessend ein C-Buch kaufen gehen.

Autor: A.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

@Peter:
Wer spricht denn hier von gegenseitig aufrufen ?

Ich hätte gerne eine Tabelle mit folgendem Eintrag:

const unsigned char table [][] = {{0x10, 0x00}; ... // Für die 1. Fkt 
z.B.

Natürlich könnte ich den Funktionpointer selbst auch ablegen, nur dann 
würde die tabelle so aussehen:

const unsigned char table [][] = {{0x1000}; ...

Nur - das will ich nicht.
Sinn der Sache ist, dass ich diese Tabelle danach in Assembler anspringe 
und da diverse register (DPH und DPL) mit dem high - und low byte 
befüllen muss.
Darum ja auch meine Frage, ob ich die konstanten ausdrücke (die sich 
nach jeder veränderung des programms ändern) durch entsprechende Makros 
ersetzen lassen.

> Wenn es aber nur ein Programm ist, dann interessiert keine Sau die absolute 
Adresse, denn der Linker löst alles auf.

Das seh ich etwas anders.

> Wer arbeitet denn heutzutage noch mit ROM ?
Es hat nicht jeder einen ATMega128 mit unendlich viel Flash zur 
verfügung.

@Karl Heinz:
Also ich glaube nicht, dass deine Antwort irgendetwas mit meiner Frage 
zu tun hat. Hätte man sich auch sparen können.

Trotzdem, danke für die Antworten.

lg. AS

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A.S. wrote:

> @Karl Heinz:
> Also ich glaube nicht, dass deine Antwort irgendetwas mit meiner Frage
> zu tun hat. Hätte man sich auch sparen können.

Dann formulier die Frage um.
Ich denke nämlich immer noch, dass eine Tabelle
aus Funktionspointern genau das ist, wonach du suchst.

Zumindest passt sie wie die Faust aufs Auge auf
dein bisheriges Anforderungsprofil:

void funcA()
{
}

void funcB()
{
}

typedef void (*Fnct)();

const Fnct table[] = { funcA, funcB };

und schon hast du eine schöne Tabelle, in der die
Speicheradressen der Funktionen funcA und funcB gesammelt
sind.

Aber bitte: Wenn du was anderes willst, dann sags ruhig.

Autor: A.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Ich möchte nicht den Funktionspointer selbst in der Tabelle speichern, 
sondern die absolute Adresse der Funktion - aufgeteilt in high - und low 
byte.
Wie gesagt, ich verwende die Tabelle später in Assembler und nicht in C.


Bitte keine Diskussionen ob das Sinn macht oder nicht - wenn einer 
irgendwelche Präprozessor/Compiler/Linker - Makros kennt, die mir helfen 
- bitte gerne. Alles andere ist nutzlos.

Vielen dank.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ A.S.

>Ich möchte nicht den Funktionspointer selbst in der Tabelle speichern,
>sondern die absolute Adresse der Funktion

Ist das nicht das Gleiche?

>Wie gesagt, ich verwende die Tabelle später in Assembler und nicht in C.

Assembler-Teile in einem C-Programm?

MFG
Falk

Autor: A.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Falk

> Ist das nicht das Gleiche?
Nein, denn ob ich in der Tabelle: 0x1000 oder 0x10,0x00 stehen habe, 
macht einen Unterschied -> zumindest in Assembler.


Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ A.S.

>> Ist das nicht das Gleiche?
>Nein, denn ob ich in der Tabelle: 0x1000 oder 0x10,0x00 stehen habe,
>macht einen Unterschied -> zumindest in Assembler.

Bisschen mädchenhaft heute?
DAS sollte sich wohl leicht herausfinden lassen und entsprechend 
handhaben. Das händische Gemurkse mit irgendwelchen absoluten 
Speicheradressen von Funktionen wird dich wochenlang beschäftigen.

MFG
Falk



Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk Brunner wrote:
> @ A.S.
>
>>Ich möchte nicht den Funktionspointer selbst in der Tabelle speichern,
>>sondern die absolute Adresse der Funktion
>
> Ist das nicht das Gleiche?

Ein Funktionspointer IST die absolute Adresse einer Funktion.
Zumindest auf einem AVR.
Die Tabelle, so wie ich sie konstruiert habe, enthält
die absoluten Adressen der Funktionen und nachdem auf einem
AVR eine Adresse aus 2 Bytes besteht enthält sie High-Byte
und Low-byte.

> Nein, denn ob ich in der Tabelle: 0x1000 oder 0x10,0x00 stehen habe,
> macht einen Unterschied -> zumindest in Assembler.

Du wirst ja wohl noch in Assembler 2 Bytes aus dem
Speicher lesen können, wenn du die Adresse der Tabelle
hast.

> wenn einer irgendwelche Präprozessor/Compiler/Linker - Makros kennt,
> die mir helfen - bitte gerne. Alles andere ist nutzlos.

Warum willst du immer auf irgendwelche Makros hinaus?
Ein Funktionspointer-Tabelle ist genau das was du willst:
Eine Tabelle in der die Startadressen der Funktionen stehen
die du in der Initialisierung anführst. Lass dich doch nicht
so zu deinem Glück zwingen. Noch einfacher und simpler geht
es nicht in C.

Autor: Andreas K. (oldcoolman)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo A.S.

falls das so funzt bei dir, denn erklär mir mal wie das so
geht. ich möchte nämlich bestehende assembler routinen in
c linken und weiss nicht wie man parameter hin und her übergibt.
bin in c Anfänger.

Danke im voraus.

nette Grüße

Andreas

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A.S. wrote:

> const unsigned char table [][] = {{0x10, 0x00}; ... // Für die 1. Fkt
> z.B.
>
> Natürlich könnte ich den Funktionpointer selbst auch ablegen, nur dann
> würde die tabelle so aussehen:
>
> const unsigned char table [][] = {{0x1000}; ...

Wenn schon denn schon:
unsigned int code table[] = { 0x1000, 0x2000 ... };

Wenn Du nicht mal weißt, daß der Compiler intern 16 Bit Werte als 2 
Bytes ablegt, dann wird das eh nichts, egal, was es werden soll.

Wenn Du die Tabelle aber eh in Assembler benutzen willst, leg sie doch 
auch in Assembler an:
table: dw 01000h, 02000h usw.

Wie man dann die beiden Bytes nach DPTR schaufelt, dürfte für jeden 
Assemblerfreak klar sein.


> Darum ja auch meine Frage, ob ich die konstanten ausdrücke (die sich
> nach jeder veränderung des programms ändern) durch entsprechende Makros
> ersetzen lassen.

Was denn nun, erst konstante Zahlen, nun wieder veränderbar ?

Veränderbare Dinge macht der Linker für Dich, Du mußt ihn einfach bloß 
lassen.


>> Wer arbeitet denn heutzutage noch mit ROM ?
> Es hat nicht jeder einen ATMega128 mit unendlich viel Flash zur
> verfügung.

Hä ?
Ich denke Du nimmst nen 8051, was soll nun der AVR dabei ?
Dein Worte werden immer verwirrter.
Ich setze auch 8051 ein, aber eben Flash und nicht ROM. Und vorzugsweise 
die mit internem Bootloader (AT89C51CC01).


Mein Tip:

Wenn Du keine Lust hast, das Compilerhandbuch und die Keil Knowledgebase 
zu lesen, wie und in welchem Speichermodell Aufrufe und 
Parameterübergaben von Assembler nach C und umgekehrt zu erfolgen haben, 
dann laß es lieber. Es wird nicht das geringste dabei rauskommen.

Außerdem müssen die Assemblerobjekte C-freundlich geschrieben sein 
(keine festen Adressen und Variablen, Export aller Namen nach den 
Linker-Regeln, gleiche Byteorder wie im C-Programm).


Meine Erfahrung:

Die Fälle, wo Mixen Assembler mit C bei mir was gebracht hat, kann ich 
an null Fingern abzählen.
Ich hatte es mal probiert und dann später auf nur C geändert ohne den 
geringsten Nachteil.
Ich hatte es dann auch so gemacht, wie in der Knowledgebase empfohlen, 
d.h. eine Dummyfunktion von C nach Assembler compilieren lassen und dann 
den Assembler dort eingefügt.
Dann sind alle Funktionen und Variablen schon C-konform.


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A.S. wrote:
> Nein, denn ob ich in der Tabelle: 0x1000 oder 0x10,0x00 stehen habe,
> macht einen Unterschied -> zumindest in Assembler.

Darf ich mal laut lachen ?

In Assembler ist es nämlich kein Unterschied:
LOC  OBJ            LINE     SOURCE

                       1
                       2
0000 1020              3             db 010h, 020h
0002 1020              4             dw 01020h

Bevor man Unsinn behauptet, sollte man es sich erstmal anschauen.

Peter

Autor: A.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
guten abend,

Wie ich sehe wurde hier schon ziemlich viel gepostest, aber leider wurde 
meine Frage immer noch nicht beantwortet.

Ich wills also nochmal versuchen.
Ich will auch noch mal klar stellen, dass ich hier nicht auf 
Verbesserungsvorschläge aus bin. Klar gibt es bessere Controller mit 
Flash statt ROM, klar kann ich den Funktionspointer (= absolute Adresse) 
direkt in der Tabelle ablegen,klar kann ich in Assembler danach die 
Bytes der Adresse aus der Tabelle lesen, klar kann man eine Mischung aus 
C und Assembler hinterfragen uvw. Da könnte man ewig weitermachen, ist 
aber absolut sinnlos und verschwendet Zeit. Wer auch immer antwortet, 
bitte nehmt meine Aufgaben - bzw. Problemstellung als gegeben hin.


Tatsache ist, es gibt in der Keil - Knowledge base das folgende Makro 
bzw. #define.

#define l_byte(v)  (*(((unsigned char *) (&v))))
#define h_byte(v)  (*(((unsigned char *) (&v) + 1)))

Mit dieser anweisung kann in C während der laufzeit den inhalt eines 
pointers in 8 - bit variablen aufteilen. (Ohne casten mit zusätzlichen 
schiebeoperationen). Das funktioniert allerdings nur für pointer die auf 
daten zeigen, d.h. nicht auf funktionen im code - bereich.

Ich brauch nun sowas für funktionen um zur compile - zeit bzw. während 
des linkens eine Tabelle zu befüllen (einzelne 8 - bit werte, nicht die 
ganze adresse auch wenn unterm strich das gleiche rauskommt). Ich möchte 
nur wissen, ob es diese möglichkeit gibt. Falls ja - toll, wenn nicht - 
pech gehabt.

@Peter
> Wenn Du keine Lust hast, das Compilerhandbuch und die Keil Knowledgebase
>zu lesen, wie und in welchem Speichermodell Aufrufe und
>Parameterübergaben von Assembler nach C und umgekehrt zu erfolgen haben,
>dann laß es lieber. Es wird nicht das geringste dabei rauskommen.

> A.S. wrote:
> Nein, denn ob ich in der Tabelle: 0x1000 oder 0x10,0x00 stehen habe,
> macht einen Unterschied -> zumindest in Assembler.

> Darf ich mal laut lachen ?

Ich mein, was soll das ? Ich stell hier nur eine Frage, wenn für dich 
das ganze lächerlich ist - dann laß es bitte sein. Es hat hier 
wahrscheinlich nicht jeder so einen enormen Wissensstand wie du. Die 
Keil - Knowledgebase ist sicher extrem umfangreich, wie auch das Keil - 
Handbuch selbst. Aber in diesem Fall hab ich keine Lösung gefunden, 
darum hab ich mich auch an das Forum gewendet. Könnte ja sein, dass 
irgend jemand irgendeinen Trick kennt, um so eine Aufgabenstellung wie 
ich sie habe, zu lösen.


Bitte nochmal, ich weiss dass man das ganze auch anders machen kann - 
aber ich will es eben so wie oben beschrieben machen.

lg.
A.S

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wem nicht zu helfen ist ...

Autor: fnah (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Roland Praml (pram)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich behaupte jetzt mal das geht nicht
(ok ich kenn mich nicht sooo toll aus, falls das nicht stimmt was ich 
schreibe, dürft ihr mich korrigieren),
aber die Tabelle willst du in C definieren und die Adressen müssten 
somit schon zur Compilezeit bekannt sein, was aber nicht der Fall ist, 
weil diese u.U. erst beim Linken bekannt werden und der Linker ja keine 
Daten ändert.

Du könntest jetzt entweder mit irgendwelchen Makros dem Linker die 
Adressen der einzelnen Funktionen vorschlagen (keine Ahnung obs dafür 
Makros gibt, ausserdem wär das eine ziemliche Holzhammer-Methode)

eine weitere Möglichkeit die mir noch einfällt, wäre eine Sprungtabelle 
an einer definierten Stelle abzulegen, z.B. mit _attribute_ ( 
section... ) (Wieder keine Anhung ob das geht) und von dieser Tabelle 
dann die einzelnen Funktionen anspringen.
Allerdings hat man dann bei einem Funktionsaufruf einen longjmp mehr

Gruß
Roland

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A.S. wrote:

> Ich mein, was soll das ? Ich stell hier nur eine Frage, wenn für dich
> das ganze lächerlich ist - dann laß es bitte sein.

Ich wollte Dir nur aufzeigen, daß der große Unterschied, auf dem Du die 
ganze Zeit drauf rumreitest, garkeiner ist.

Darum dürfte sich auch keiner die Mühe gemacht haben, für eine 
Nichts-tun-Funktion ein extra Macro zu schreiben.

Das einzige, was man mit dieser Funktion erreichen könnte:
Man könnte damit die Byteorder gegenüber der Defaultvorgabe des 
Assemblers und Compilers umdrehen, damit man noch mehr Fehlerquellen in 
seinem Programm hat.


Und wenn Du nicht mal das Assemblerlisting verstehst, solltest Du umso 
mehr die Finger davon lassen.


Peter

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du brauchst keine Macros, um die Funktionsadresse in eine Tabelle zu 
speichern - das ist das täglich Brot eines jeden Compilers und das 
beherrscht der sozusagen im Schlaf.

Nimm einfach ein Array von Funktionspointern, wie oben schon 
beschrieben, oder ein Array von void pointern, falls die Funktionen 
unterschiedliche Signaturen haben und initialisiere es mit den 
Funktionspointern.

Jedesmal, wenn sich durch Änderungen an Deinem Programm irgendwelche 
Funktionsadressen ändern, trägt der Compiler automatisch die neue 
Adresse in die Tabelle ein.

In Deinem Assemblerprogramm greifst Du dann einfach indiziert in die 
Tabelle, um die jeweils gültige Funktionsadresse zu bekommen.

Solange die Reihenfolge der Funktionen in der Tabelle nicht verändert 
wird, findet das Assemblerprogramm immer den richtigen Wert - 
vorausgesetzt es weiß, wo es die Tabelle findet.

@ Alle, die meinen, das sei absoluter Murks, was A.S. da vor hat:
Ihr seid auf dem Holzweg. Das ist eine Methode, wie sie auf Eurem PC 
täglich Millionenfach angewandt wird: Nämlich bei jedem Funktionsaufruf 
in eine DLL.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Uhu Uhuhu wrote:

> @ Alle, die meinen, das sei absoluter Murks, was A.S. da vor hat:

Nö, Funktionspointer sind kein Murx, nehme ich oft, z.B. für nen 
Kommandointerpreter.

Bloß die sture Rumreiterei auf der Schreibweise als einzelne Bytes ist 
Murx.
In ner 8Bit-Maschine sind alles nur Bytes.
Und wie nun 2 oder mehrere aufeinanderfolgende Bytes interpretiert 
werden, hängt allein vom Programm ab und nicht davon, wie man sie 
hinschreibt.


Peter

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Uhu Uhuhu

>Nimm einfach ein Array von Funktionspointern, wie oben schon
>beschrieben, oder ein Array von void pointern, falls die Funktionen
>unterschiedliche Signaturen haben und initialisiere es mit den
>Funktionspointern.

Das wollten ihm ein halbes Dutzend Leute bereits verklickern. Er ist 
aber etwas begriffstutzig.

>@ Alle, die meinen, das sei absoluter Murks, was A.S. da vor hat:
>Ihr seid auf dem Holzweg. Das ist eine Methode, wie sie auf Eurem PC
>täglich Millionenfach angewandt wird: Nämlich bei jedem Funktionsaufruf
>in eine DLL.

Na ein Glück dass DU uns aufklärst!

MFG
Falk

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Bloß die sture Rumreiterei auf der Schreibweise als einzelne Bytes ist
> Murx.

Finde ich nicht. A.S. ist weniger ein Murkser, als ein Anfänger, der 
eben mit gewissen Problemen zu kämpfen hat...

Murkser sind Fortgeschrittene, die eigentlich keine Lust haben.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Uhu Uhuhu wrote:

> Finde ich nicht. A.S. ist weniger ein Murkser, als ein Anfänger, der
> eben mit gewissen Problemen zu kämpfen hat...

Das war auch mein Eindruck und genau deshalb rate ich ab, Assembler und 
C zu mixen.
Wer das vorhat, muß beides gut beherrschen.

Wer aber irgendwann C leidlich gut kann, merkt plötzlich, daß Mixen mit 
Assembler nicht mehr nötig ist.


Peter

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wer aber irgendwann C leidlich gut kann, merkt plötzlich, daß Mixen mit
> Assembler nicht mehr nötig ist.

Daß das nicht mehr nötig ist, kann man so allgemein nicht sagen.

Auf jeden Fall ist es für jeden C-Programmierer eine sehr wertvolle 
Erfahrung, wenn er das Assemblerhandwerk gut beherrscht.

Deswegen A.S.: Laß Dich nicht ins Bockshorn jagen! - Aber nimm Dir auch 
nicht gleich zu Beginn zu viel vor!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger wrote:

> Bloß die sture Rumreiterei auf der Schreibweise als einzelne Bytes ist
> Murx.

Wobei sich natürlich die Frage stellt: Warum will er das
überhaupt unbedingt als einzelne Bytes in die Tabelle
schreiben? Den einzigen Grund den ich mir vorstellen könnte,
ist es die Byteorder zu kontrollieren. Auf der anderen
Seite: Wenn ich das Auslesen sowieso unter Kontrolle habe,
noch dazu in Assembler, in dem die Reihenfolge nun wirklich
keine Rolle spielen sollte, ist das ein 0-Argument.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachdem jetzt die Frage, wie mit Funktionspointern umgegangen werden 
kann, geklärt ist, ist noch eine weitere offen:

Wie kann man einen Funktionspointer in einzelne Bytes zerlegen?

Auch wenn man das in der Praxis eigentlich nie braucht, kann man aus der 
Antwort etwas über C lernen.

Für Datenadressen funktionieren die von A.S. geposteten Macros

#define l_byte(v)  (*(((unsigned char *) (&v))))
#define h_byte(v)  (*(((unsigned char *) (&v) + 1)))

Warum gehen sie mit Funktionsadressen nicht?

Ganz einfach: Wenn v ein Funktionspointer ist, dann ist das eine 
Konstante, wie z.B. 43 - und Konstanten haben keine Adressen.

    l_byte(43)

erzeugt denselben Syntaxfehler, wie

    l_byte(funcA)

Man muß also den Adressoperator & vor dem v weglassen, denn der gibt die 
Adresse - ebenfalls eine Konstante - seines Operanden zurück:

    #define const_l_byte(v)  (*(((unsigned char *) (v))))

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal ein Beispiel für Funktionspointer aufm 8051:
typedef unsigned char u8;

typedef u8(code *u8funcv)(void);        // function pointer,
                                        // input: void,
                                        // return: unsigned char


u8 func0(void);                         // some external functions
u8 func1(void);
u8 func2(void);


u8funcv code func_table[] = {           // table of function pointers
        func0,                          // in code memory segment
        func1,
        func2
};


u8 execute( u8 func_no )
{
  if( func_no >= sizeof(func_table) / sizeof(u8funcv))
    return 255;                                         // out of table

  return func_table[func_no]();                         // do it
}


Dazu muß man wissen, daß der 8051 verschiedene Memory-Segmente hat.
Pointer ohne Memory Specifier werden als generic Pointer angelegt 
(3Byte).
Daten ohne Memory Specifier werden im default Data Memory abgelegt (je 
nach Memory Model).

Das "code" im typedef definiert einen Pointer auf den Code-Memory.
Und das "code" in der Tabelle legt die Tabelle nicht im SRAM, sondern im 
Flash an.

Funktionieren tuts auch ohne beides, braucht aber mehr SRAM und Flash.


Peter

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.