Hi Leute,
Ich verstehe die Parameterübergabe beim Infineon C515C-L nicht, kann
mich da bitte einer aufklären. Ich habe:
1
codechartext1[]="Text-1";
2
codechar*text2="Text-2";
Wenn ich nun diese zwei einzeln puts übergebe, so entstehen folgende
Codes:
1. Für puts(text1):
1
MOV R3, #0xFF
2
MOV R2, #HIGH (text1)
3
MOV R1, #LOW (text1)
4
LCALL _PUTS
2. Für puts(text2):
1
MOV DPTR, #text2
2
CLR A
3
MOVC A, @A+DPTR
4
MOV R3, A
5
MOV A, #01H
6
MOVC A, @A+DPTR
7
MOV R2, A
8
MOV A, #02H
9
MOVC A, @A+DPTR
10
MOV R1, A
11
LCALL _PUTS
Ich versteh nicht:
1. Wieso bei "text1" R3 "0xFF" sein muss
2. Wieso bei "text2" ich insgesamt 3 Parameter (24-Byte) brauche, obwohl
zur Adressierung nur 16-Bit notwendig sind.
Danke im Voraus!
Steffan schrieb:> 2. Wieso bei "text2" ich insgesamt 3 Parameter (24-Byte) brauche, obwohl> zur Adressierung nur 16-Bit notwendig sind.
Das alles sollte im Manual zum Compiler stehen. Vielleicht unter Generic
Pointer. Denn der braucht außer dem Datenbereich noch Zusatzinfo, wo er
liegt, im internen RAM, im Flash, oder wo auch immer.
Es heißt in der Doku nur, man müsse R3, R2 und R1 hernehmen und dass R3
"memory type", R2 "High-Byte" und R1 "Low-Byte" wäre für "generische
Pointer". Doch wenn wir uns mein Beispiel ansehen, so wird R3 als
"High-Byte" bei "text2" hergenommen. Das ist zu ungenau formuliert.
Steffan schrieb:> Wieviele von euch setzen sich so tief mit der Materie auseinander?
Ich.
Allerdings habe ich für die 8051 und 80C515 und 80C517 den
SDCC-Compiler, nichts kommerzielles.
Da mußte ich mich mit Pointern und Übergabeparametern schon mal mit
auseinander setzen, als ich in C eingebundene externe Assemblerfiles
schrieb.
In einem dritten Byte wird dort der Speichertyp oder Pointer für einen
16-bit-Wert übergeben.
Steffan schrieb:> Ja aber was ich nicht versteh ist:> Bei "text1" ist R3 "0xFF" und bei "text2" ist es das High-Byte.> Was ist die Logik dahinter?
Die 0xFF bedeuten vom Wert her an sich nichts. Es ist nur eine
Vereinbarung des Compilers.
Bei meinem SDCC-Compiler stehen da z.B. Werte wie 0x40, 0x80, 0xC0 oder
ähnliches drin, einfach für ein Nachfolge-Programmteil, damit es den
Speicherbereich sieht. Damit kann ich dann in einem nach folgenden
selbst gemachten Assemblercode schauen, ob ich auf internes RAM oder
XRAM oder externes RAM oder auf den Codebereich (z.B. ein im Flash
abgelegtes Konstanten-Array) zu greife.
1. Das steht z. B. in der Doku nicht mit dabei (bin durch die
source-Datei drauf gekommen)
2. Sowohl text1 als auch text2 sind mit "code" deklariert, also im
gleichen Speicher. Wieso ist denn bei "text1" ist R3 "0xFF" und bei
"text2" das High-Byte?
Das ist der Punkt den ich einfach nicht verstehe: Wieso ist es nicht
einheitlich? Woher soll ich wissen, dass es so ist, wenn es nicht einmal
in der Doku von Keil steht.
Sorry, Steffan, ich kann es dir nicht nehmen, und verstehe etwas Unmut.
Ich habe ihn nicht produziert, und muß selbst mit den Dingen zurecht
kommen. Das ist heute so. Nicht einfach los legen, und machen, irgendwo
kommt ein Fall, da muß man Datenblätter und Manuals immer wieder lesen,
lesen, lesen, und noch mal lesen.
Steffan schrieb:> 1. Das steht z. B. in der Doku nicht mit dabei (bin durch die> source-Datei drauf gekommen)
Kannst du 8051-Assembler? Das ist da sehr hilfreich.
> 2. Sowohl text1 als auch text2 sind mit "code" deklariert, also im> gleichen Speicher. Wieso ist denn bei "text1" ist R3 "0xFF" und bei> "text2" das High-Byte?
Also, da mußt du wie in Punkt 1 beschrieben, den Assemblercode mal
schrittweise nachvollziehen, und genau verfolgen, was da im Verlauf mit
dem Inhalt 0xFF in R3 passiert.
Welchen Compiler hast du eigentlich?
Ich hab den C51-Compiler von Keil. Wenn es irgendwo dokumentiert wär,
wie die Parameterübergabe genau passiert, dann hätte ich hier nicht
nachgefragt. Es heißt auf der Seite von Keil nur: R3, R2 und R1 würden
für "generische Pointer" hergenommen werden. Das ist alles, mehr kann
man zu dem Thema nicht finden. Ich hab nichts darüber gefunden, wo
detailliert steht welches der Register R3 - R2 für was hergenommen wird.
Steffan schrieb:> Hier steht z. B., dass R3 immer das "mem type" ist hergenommen wird es> bei "text2" hingegen als "High-Byte"..
Warum soll es das high Byte sein?
Es wird wahrscheinlich genau wie bei text1 "mem type" sein, nur steht es
halt unmittelbar vor der 16 Bit Adresse.
Dieter Werner schrieb:> Es wird wahrscheinlich genau wie bei text1 "mem type" sein, nur steht es> halt unmittelbar vor der 16 Bit Adresse.
Mannnnnn!!! Das steht doch ausgerechnet bei Keil bestimmt alles im
Manual!!!
Steffan schrieb:> Es ist natürlich einfach zu sagen, dass alles im Manual steht...
Ich weiß. Manchmal mußte ich auch drei Tage im Manual (SDCC) lesen, um
eine Sache zu begreifen, ohne mich jetzt hier als Dumpfbacke hin stellen
zu wollen.
Nämlich meistens, wenn man nirgendwo Beispiele findet.
Das Problem ist nicht, dass ich nicht lesen kann. Es gibt Sachen, die
stehen im Manual leider nicht ausführlich drinnen. Es gibt keine
detaillierten Infos über das Problem das ich erläutert habe. Das einzige
was ich machen kann ist, dass ich das ganze vom Compiler abkucke ohne zu
verstehen, wieso das so gemacht wird..
Steffan schrieb:> Das einzige> was ich machen kann ist, dass ich das ganze vom Compiler abkucke ohne zu> verstehen, wieso das so gemacht wird..
Du hast ein Problem: Du kannst keinen 8051-Assembler.
Leider wird das von C-Befürwortern auch hier im Forum immer wieder als
nichtsnützig und unnötig deklariert. Assembler braucht keine Sau niemals
nicht mehr. Aber in Wahrheit ist es nicht so.
Ja weil ich mir dieser Wahrheit bewusst bin geh ich dieser Wahrheit auch
nach. Und ob dus mir glaubst oder nicht: Nur durchs Debuggen und der
Compilerausgabe bin ich jetzt draufgekommen, dass bei "text2" ebenfalls
"0xFF" in "R3" abgelegt wird und nicht wie vermutet das Highbyte.
Willhelm kannst du mir dann bitte eine Erklärung oder einen Link nennen,
wo steht, wann man für "R3" (memory type) welchen Wert angeben muss? Ich
bin immer noch auf der Suche, hab aber keine Erklärung gefunden.
Steffan schrieb:> dass bei "text2" ebenfalls> "0xFF" in "R3" abgelegt
Es steht auch bei beiden das Schlüsselwort code davor. Dann sind sie
auch beide im selben Speicherbereich. Mach das code mal weg, und
schau, was dann passiert. Die sollten dann im RAM abgelegt werden, und
in R3 was anderes drin stehen. Als Code werden dann auch nicht mehr
movc-Befehle generiert, sondern vielleicht mov oder movx.
Soweit war ich auch schon. Die Compilerausgabe zu lesen ist ja einfach..
Nur ist es schwierig zu sagen, wieso für R3 mal 0xFF bei
"code"-Variablen und mal "0x00" bei normalen Variablen hergenommen wird.
Nirgends ist die Codierung einsehbar. Wie soll man da vernünftig
Assembler programmieren, wenn man bei diesem Problem nur vom Compiler
abkucken kann?
Steffan schrieb:> Nur ist es schwierig zu sagen, wieso für R3 mal 0xFF bei> "code"-Variablen und mal "0x00" bei normalen Variablen hergenommen wird.
Der Compiler produziert für verschiedene Speicherbereiche sehr
verschiedenen Assemblercode. Das liegt im 8051-Befehlssatz. Er hat
Befehle für internes RAM, indirektes internes RAM, externes RAM, und
Programmspeicher.
Manchmal begreift man das richtig, wenn man einen 515 mal rein in
Assembler programmierte.
Soweit wahr ich auch schon :). Das ist mir schon klar. Nur was bedeutet
die Codierung "0xFF", "0x00" u.s.w.. Wo kann man das nachlesen, welcher
Code, was bedeutet? (außer vom kompilierten abzukucken)?
Wo ist das Problem?
Puts braucht in R3 den Memory-Typ und in R2,1 die Adresse.
Text1 ist ein String, da kann er die Register direkt laden.
Text2 ist aber ein Pointer, also muß er diesen Pointer auslesen und nach
R3,2,1 laden.
Ist alles korrekt.
Aus dem Keil Handbuch zum C51:
Seite 178 (Thema Pointer):
Memory Type idata / data /bdata Xdata pdata code
C51 Compiler 0x00 0x01 0xFE 0xFF
CX51 Compiler 0x7F 0x00 0x00 0x80
und auf Seite 164 wird Parameter Passing abgehandelt. Die Tabelle ist
leider etwas komplex und will sich partout hier nicht guttenbergen
lassen. In R3 wird der Speichertyp übergeben.
Steffan schrieb:> In welchem Manual steht das ?
Ist beim KEIL Paket dabei, auch in der freien Version. C51.PDF nennt
sich das File, im Verzeichnis ~/C51/HLP, gut 1.3MB
Georg G. schrieb:> Bei Keil, wo sonst? Die schicken dir sogar eine CD, falls du Probleme im> Download hast. Das sind auch sonst sehr nette Leute, wenn man Fragen> hat.
Das ist doch Unsinn. Die verkaufen Ihre Entwicklungsumgebungen für gutes
Geld. Frei Version: Quatschkopf.
Wenn du irgendwann mal erwachsen wirst, lernst du vielleicht dazu:
https://www.keil.com/c51/demo/eval/c51.htm
Die maximale Größe des fertigen Codes ist begrenzt, reicht aber für
viele Hobbyprojekte aus. Und die Doku ist vollständig und gut.
Nicht daß ich C auf x51 jemals gemacht hätte, aber
text1 ist ein char arry in code, hat 16addr und memtyp code, beide const
text2 ist ein in code liegender pointer auf char, ein generischer, 3byte
pointer, denn der mentyp von char ist nicht angegeben
Also eher ein erweitertes C-Versteh-Problem.(zugegebenermaßen nicht
trivial)
Als Compiler könnte man natürlich erkennen,daß dieser Pointer sich nie
ändern sollte, sein Zielbereich und dessen Offset bekannt ist.
Allerdings habe ich schon gesehen, daß x51 mit Flash auch leicht vom
laufenden Programm aus geändert werden kann, also nicht zwingend const
ist.
Steffan schrieb:> kann> mich da bitte einer aufklären
Das ist der Unterschied zwischen array und pointer. Compiliere und Linke
das Programm einmal in der Version array und einmal mit der Version
pointer. Vergleiche anschließend die Mapfiles in der Speicherverwendung.
C gcc schrieb:> Also eher ein erweitertes C-Versteh-Problem
Ein wenig vielleicht auch ein 8051-Versteh-Problem.
Der 8051 ist ja in Harvard-Architektur. Er hat also zwei Adreßbereiche,
Code und Xdata, welche quasi die gleichen Adressen haben. Auf diese
Bereiche wird über das 16-bit-Register DPTR (Data Pointer) zugegriffen,
aber mit separaten Befehlen. Also braucht man noch ein zusätzliches
Unterscheidungsmerkmal, das ist eben das dritte Byte im
Parameter-Passing. Außerdem hat der 8051 auch noch einen Idata-Bereich,
ebenfalls mit den gleichen Adressen. Dort wird aber nur ein 8-bit-Wert
für den 8-bit-Pointer gebraucht, und das zweite Byte kann leer bleiben.
Keil unterstützt auch noch Banking von Code und Xdata, so daß man den
8051 (auch 80C515 und 80C517 und viele andere Derivate) mit einem
Vielfachen des normalen maximalen Speicherausbaues von 64k gestalten
kann. Ursprünglich war das vom Chiphersteller mal gar nicht vorgesehen,
weil man glaubte, daß 64k für alle Zeiten reichen würde. Da wird es auch
wieder etwas komplizierter, es werden dort anderweitig noch freie
I/O-Pins für die Speicheradressierung mit heran gezogen, auf die man
dann für andere I/O-Zwecke verzichten muß. Ich brauchte das selbst nie,
habe nur mal ein wenig in diese Techniken geschnuppert. Man kann sich
das Banking aber auch mit jedem anderen Compiler oder Assembler selbst
gestalten, es ist nur etwas aufwändig. In einem alten Faxgerät fand ich
einmal tatsächlich einen 8051 mit einem Megabyte-EPROM, dort wurde es
also angewandt. Zu sehen waren im EPROM tatsächlich in 64k-Abständen die
Interruptvektoren. Dann muß das EPROM in jeder 64k-Bank auch ein
Bankumschaltungsprogramm haben. Man muß da bei der Programmierung also
Vorsicht walten lassen. Da sind moderne Controller heute bequemer. Im
Prinzip funktioniert diese Bankumschaltung etwa wie die Überschreitung
einer Landesgrenze mit einer älteren Allstrom-Eisenbahnlok.
Aber ich schlug dem TO ja bereits gestern schon vor, die beiden
Speicherreservierungen nicht im Code anzulegen, sondern in Data bzw.
Xdata. Dann wird er im R3 nicht den Wert 0xFF finden, sondern 0xFE, und
auch anderen compilierten Code.