Hallo,
was bedeutet diese Codezeile:?
register unsigned char DATA[24];
vor allem was bringt das register davor... heißt das, dass die variable
direkt mit einem Register verknüpft wird?
Vielen Dank
Gruß
Martin
Was Deine Zeile bedeutet weiss ich nicht. :)
Als Tip vielleicht:
register unsigned char counter asm("r3");
Bedeutet, dass die Variable "counter" permanent in r3 bleiben soll.
Vielleicht hilft das ja irgendwie weiter...
Grüße
Tobi
Woher hast Du denn die Codezeile? Normalerweise bedeutet register, der
Variable immer ein Register zuzuweisen, d.h. sie kommt auch nie ins
RAM. Der Zugriff ist entsprechend schnell. Aber in Deinem Beispiel ist
ja ein ganzes Array zugeordnet. Da macht das keinen Sinn?
Stefan
Die originale Zeile würde sich vom Compiler wünschen, das komplette
Array DATA in Registern unterzubringen. Obwohl der AVR 32 Register
hat, wird Dir der Compiler ohnehin kaum so viel bewilligen. ;-)
`register' in seiner Originalform war für alte Compiler wichtig, um
dem Compiler eine Hilfestellung zu geben, welche Variablen er
vorzugsweise in Registern unterbringen soll. Aktuelle Compiler
ignorieren das Schlüsselwort in aller Regel, da ihre Optimizer das
selbst vernünftig entscheiden können.
Die Zeile stammt ürsprünglich aus einem Program für den
Dunfield Development Systems Micro/C AVR compiler
Ich hab das "register" jetzt einfach entfernt, und es funktioniert.
Martin
@ Jörg
Das stimmt so nicht ganz.
Die Zeile, die ich oben geschrieben habe ist eine Vorschrift, d.h. der
Compiler wird es so machen.
Der Grund ist u.A. dass ich z.B. eine Assembleroutine schreiben kann
und weiss, dass bestimmte Werte IMMER in diesen Registern stehen. D.h.
auch, dass der Compiler sie nicht vorrübergehend anders belegen kann,
da ja genau in diese Zeitraum der Interrupt ausgelösst werden könnte.
Es gibt andere möglichkeiten, dem Compiler zu "empfehlen" bestimme
Variabeln in Registern zu halten. Was er mit einer "empfehlung" macht
ist seine Sache.
Grüße
tobi
> Die Zeile, die ich oben geschrieben habe ist eine Vorschrift,> d.h. der Compiler wird es so machen.
Sorry, das ist Quatsch.
Offensichtlicher Gegenbeweis: der GCC macht aus diesem Stück Code
unsigned char
foo(void)
{
register unsigned char foo[24];
return foo[3];
}
folgendes (mit Optimierung, ohne Generierung irgendeiner Warnung):
foo:
push r28
push r29
in r28,__SP_L__
in r29,__SP_H__
sbiw r28,24
in _tmp_reg_,__SREG__
cli
out _SP_H_,r29
out _SREG_,__tmp_reg__
out _SP_L_,r28
ldd r24,Y+4
clr r25
adiw r28,24
in _tmp_reg_,__SREG__
cli
out _SP_H_,r29
out _SREG_,__tmp_reg__
out _SP_L_,r28
pop r29
pop r28
ret
Die Berechnung des Stackoffsets ist gut zu erkennen, auch die
Reservierung von 24 Bytes auf dem Stack.
Zweitens: Zitat aus dem C-Standard:
``6.7.1 Storage-class specifiers
...
A declaration of an identifier for an object with storage-class
specifier register suggests that access to the object be as fast as
possible. The extent to which such suggestions are effective is
implementation-defined.''
Nichts von wegen ,,Vorschrift''. `suggests' und `as fast as
possible'.
Das bezieht sich auf die originale, standardgemäße Form der register
storage-class, aber darauf hatte ich ausdrücklich verwiesen.
Der GCC-ismus des Ablegens in einem bestimmten Register ist beim GCC
ordentlich dokumentiert und nicht ganz ohne Pferdefüße.
Hmm.
Wenn ich mich recht erinnere ist der Unterschied allerdings, dass ich
ein festes Regsiter zuweise und nicht empfehle, die Variable allgemain
im Register zu halten.
Zweitens kann ich schlecht ein Array auf beliebig viele Register
verteilen.
Drittens wird die Variable hier lokal angelegt, weswegen sie ausserhalb
der Funktion sowieso ihre Gültigkeit verliert und somit der
Registerplatz freigemacht werden muss.
Und zu guter letzt steht in der Beschreibung des AVR-gcc ausdrücklich,
dass die Variable so permanent an dieses Register gebunden wird. (siehe
FAQ des AVR-gcc)
Ich bestehe nur so darauf, da wir ein größeres Projekt besierend auf
darauf aufgebaut haben, was auch wunderbar funktioniert.
Grüße
Tobi
Da steht's:
This can be done with
register unsigned char counter asm("r3");
See C Names Used in Assembler Code for more details.
Und unter dem Verweiss findet man:
With AVR-GCC you can specify the use of a specific register:
void Count(void)
{
register unsigned char counter asm("r3");
... some code...
asm volatile("clr r3");
... more code...
}
The assembler instruction, "clr r3", will clear the variable counter.
AVR-GCC will not completely reserve the specified register. If the
optimizer recognizes that the variable will not be referenced any
longer, the register may be re-used. But the compiler is not able to
check wether this register usage conflicts with any predefined
register. If you reserve too many registers in this way, the compiler
may even run out of registers during code generation.
Was so viel heisst wie:
Falls die Optimierung feststellt, dass das Register nicht mehr
referenziert wird, DANN wird es anderweitig vergeben.
Dies kann allerdings nicht geschehen, wenn es global definiert wird.
Der nette Hinweis darunter verrät auch, dass der Compiler die Register
nicht wegoptimieren kann, sonst könnten ihm die Register kaum
ausgehen.
Grüße
Tobi
Zitiat:
"`register' in seiner Originalform war für alte Compiler wichtig, um
dem Compiler eine Hilfestellung zu geben, welche Variablen er
vorzugsweise in Registern unterbringen soll. Aktuelle Compiler
ignorieren das Schlüsselwort in aller Regel, da ihre Optimizer das
selbst vernünftig entscheiden können."
und
"Sorry, das ist Quatsch.
Offensichtlicher Gegenbeweis: der GCC macht aus diesem Stück Code
..."
So ausdrücklich war es vielleicht doch nicht. Zumindest sehe ich hier
ein "...aktuelle Compiler..." und " ... der GCC macht ...".
Wir haben wohl einfach aneinander vorbeigetextet. Ich hätte ja auch
kenntlicher machen können, dass ich hier von avr-gcc rede.
Grüße
Tobi
Naja, insbesondere hast Du von der GCC-Erweiterung geredet, mit der
man globale Variablen auf ein Register zuweisen kann. Das ist aber
non-standard.
Die Originalzeile war dagegen Standard-C -- und die ist in der Form
ziemlich überflüssig. Auf einer UltraSPARC mit ihren vielen
64-Bit-Registern mag es ja der Compiler noch akzeptieren, 24 Zeichen
in 3 Registern unterzubringen, aber auf einem Controller? :-)