Forum: Compiler & IDEs Variablen eine General Purpose Register Adresse zuweisen


von delicious_cake (Gast)


Lesenswert?

hallo,

ich möchte aus speichergründen und geschwindigkeitsgründen einige meiner 
variablen in registern ablegen. Zusaetzlich bringt das ja noch mehr 
Geschwindigkeit.

das habe ich in einem projekt entdeckt.
1
register uint8_t volatile pos asm("r3"); //8Bit Variable pos in Register r3
2
register uint16_t volatile wartezeit asm("r4"); //16Bit Varibale in Register r4:r5
3
register uint8_t volatile delta_pos1 asm("r6"); //delta_pos zur Verschiebung in Register r6
4
register uint8_t volatile delta_pos asm("r7"); //delta_pos1 bei Neustart der LAufschrift in r7
5
register uint16_t volatile _size asm("r8"); //16Bit Variable _size in Register r8:r9
6
register uint8_t volatile _laufschrift asm("r12");//_laufschrift in Register r12

das ganze habe ich für meinen fall angepasst

z.B. mit diesen registen
in dieser Variante
1
register volatile uint8_t  next    asm("r3");
2
register volatile uint8_t  i       asm("r4");
3
register volatile uint16_t seconds asm("r5"); //soll r5:r6 sein

und in diese Schreibweise
1
register uint8_t  volatile next    asm("r3");
2
register uint8_t  volatile i       asm("r4");
3
register uint16_t volatile seconds asm("r5"); //soll r5:r6 sein

allerdings funktioniert das bei mir nicht so ganz.

ich erhalte eine compiler fehlermeldung:
GenericHID.c:95: error: expected '=', ',', ';', 'asm' or '__attribute__' 
before 'asm'
GenericHID.c:96: error: expected '=', ',', ';', 'asm' or '__attribute__' 
before 'asm'
GenericHID.c:97: error: expected '=', ',', ';', 'asm' or '__attribute__' 
before 'asm'

was muss ich aendern, damit es wie im anderen Projekt funktioniert? 
fehlt mir evtl. ne header Datei die ich inkludieren muss?

danke im voraus für jede Antwort
delicious_cake

von Oliver (Gast)


Lesenswert?

delicious_cake schrieb:
> ich möchte aus speichergründen und geschwindigkeitsgründen einige meiner
> variablen in registern ablegen.

Bei solchen Vorhaben gibt es eine Standard-Gegenfrage:

Warum?

delicious_cake schrieb:
> was muss ich aendern, damit es wie im anderen Projekt funktioniert?

Du solltest den Compiler benutzen, der das "andere Projekt" fehlerfrei 
kompilieren kann.

Oliver

von delicious_cake (Gast)


Lesenswert?

ps: es handelt sich um globale Variablen

µC = AT90USB162

von delicious_cake (Gast)


Lesenswert?

Oliver schrieb:
> Warum?

der verfügbare sram ist aus. bzw. muss was für den heap übrig bleiben. 
sonst kommts zu fehlern.

Oliver schrieb:
> Du solltest den Compiler benutzen, der das "andere Projekt" fehlerfrei
> kompilieren kann.

ne sinnlosere antwort hab ich noch nie bekommen. ich habe beide auf 
meinem rechner kompiliert.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

delicious_cake schrieb:

> ich möchte aus speichergründen und geschwindigkeitsgründen einige meiner
> variablen in registern ablegen. Zusaetzlich bringt das ja noch mehr
> Geschwindigkeit.

Wenn es optimal läuft vielleicht.

Im schlechten Fall behindert deine "Optimierung" den Compiler. Es fehlen 
dem dann die Arbeitsregister und der Restcode wird durch zusätzliche 
Push/Pops speichermäßig (Stack) aufgebläht und verlangsamt.

> der verfügbare sram ist aus. bzw. muss was für den heap übrig bleiben.
> sonst kommts zu fehlern.

Wurde der Code bereits kritisch angesehen? Konstante Daten auslagern 
(Flash), Datentypen kritisch hinterfragen und globale Variablen 
reduzieren?

von delicious_cake (Gast)


Lesenswert?

Stefan B. schrieb:
> Wurde der Code bereits kritisch angesehen?

ich habe den lufa usb stack eingebunden. der bindet mir ziehmlich die 
haende. fast 50% des srams gehen dabei für den stack und den heap drauf. 
jetzt will ich halt in die nicht verwendeten register, vor allen die 
general purpose register auslagern. im vergleich zur unoptimierten 
variante meines programms habe ich bereits 25% sram frei bekommen.

kann mir endlich jemand sagen wie ich den fehler beim compilieren 
beheben kann?

von Karl H. (kbuchegg)


Lesenswert?

delicious_cake schrieb:

> kann mir endlich jemand sagen wie ich den fehler beim compilieren
> beheben kann?

vergiss es einfach.
Dem Compiler bei der Registerbelegung ins Handwerk zu pfuschen ist eine 
extrem schlechte Idee, die schief geht sobald dein Code mehr als sagen 
wir mal 10 Zeilen C Code umfasst.

Du tust dir damit nichts gutes.
Löse deine Probleme richtig und spekuliere nicht damit, dass du schlauer 
bist als dein Compilerbauer. Du bist es nicht (und ich auch nicht)

> Zusaetzlich bringt das ja noch mehr Geschwindigkeit.

Der Schuss geht mit an Sicherheit grenzender Wahrscheinlichkeit sowieso 
nach hinten los.
Und ob du weniger Speicher verbrauchst ist auch fraglich.
Jedes Register, das du fix belegst, kann dazu führen, dass der Compiler 
bei Berechnungen Zwischenergebnisse anstelle von in Registern, auf dem 
Stack zwischenparken muss.
Mal ganz davon abgesehen, dass du dann auch die komplette 
Runtime-Library neu übersetzen musst. Diese Funktionen müssen ja 
schliesslich auch wissen, dass diese Register nicht mehr zur Verfügung 
stehen.


Das Schlüsselwort 'register' hatte mal seie Berechtigung. Die Zeiten 
sind aber lange vorbei. Und das fixe Binden von Variablen an Register 
macht bis auf Micky Maus Programme, die keine Standard-Library benutzen, 
keinen oder kaum Sinn.

von Sauger (Gast)


Lesenswert?

Mahlzeit,

die General Purpose I/O Register GPIOR0/1/2 sind erlaubt.

MfG

von Oliver (Gast)


Lesenswert?

delicious_cake schrieb:
>> Du solltest den Compiler benutzen, der das "andere Projekt" fehlerfrei
>> kompilieren kann.
>
> ne sinnlosere antwort hab ich noch nie bekommen. ich habe beide auf
> meinem rechner kompiliert.

Kompiliert hast du dein Projekt nicht, das lässt sich ja nicht 
kompilieren. Wenn das "andere Projekt" sich kompilieren lässt, musst du 
da halt richtig abschreiben.

Eigentlich hat Karl Heinz ja schon alles dazu gesagt. Ergänzend kann man 
noch, daß der gcc "register volatile" sowieso nicht versteht, insofern 
ist selbst bei fehlerfreier Kompilierbarkeit deines "anderen Projekts" 
dessen Funktion mehr als fraglich.

Beitrag "Variable an Register binden - ich kanns nicht oder compilerbug :)"

Oliver

von delicious_cake (Gast)


Lesenswert?

erst mal danke für die antworten. mittlerweile hab ich mich in die 
problematik der optimierung eingelesen und verstehe auch warum dass mit 
den registern nicht in allen faellen besonders ratsam ist.

jedenfalls geht mir der ram aus und ich brauche ne möglichkeit etwas 
davon frei zu kriegen. in diesem anderen Projekt ist dadurch ein 
erheblicher Geschwindigkeitsschub gelungen. Mein Projekt und das andere 
sind sehr aehnlich, deshalb dachte ich es waere einen versuch wert die 
gp register zu benutzen. wenn ich mein programm im simulator lange 
laufen lasse und dabei verschiede aktionen durchführe bleiben 11 
register unveraendert. diese könnten denke ich also verwendet werden. 
und wenn nich gut hinhaut, dann halt nicht. dann muss ich mir was 
anderes suchen.

von delicious_cake (Gast)


Lesenswert?

ich habs jetzt hinbekommen. ich habe dazu ein paar compiler optionen 
setzen müssen.

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -D AVRGCC -Wall -gdwarf-2  -Os -fsigned-char
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d
CFLAGS +=-std=gnu99

von Oliver (Gast)


Lesenswert?

delicious_cake schrieb:
> ich habs jetzt hinbekommen.

Hast du denn auch mal im generierten Assembler-Listing überprüft, ob der 
Compiler auch das macht, was du gerne hättest?

Oliver

von delicious_cake (Gast)


Lesenswert?

ja, es funktioniert alles wie es sollte. ich hab zum testen mal schnell 
die variablen in register gelegt die am öftesten verwendet werden. 
bisher nur insgesamt 4 Byte, aber die ausführungszeit hat sich erheblich 
verbessert.

von Rolf Magnus (Gast)


Lesenswert?

Das erstaunt mich. Waren die vielleicht auch schon davor volatile, aber 
es wurde sehr oft darauf zugegriffen? Das sollte man nicht nur aus 
Performancegründen vermeiden.

von delicious_cake (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Waren die vielleicht auch schon davor volatile, aber
> es wurde sehr oft darauf zugegriffen?

ja die waren vorher schon volatile, und ja es wird sehr oft darauf 
zugegriffen. deshalb wollte ich die ja stetig im register halten.

von Rolf Magnus (Gast)


Lesenswert?

An vielen Stellen reicht es für gewöhnlich, die Variable in eine lokale 
variable zu kopieren und damit zu arbeiten. Das hat auch den Vorteil, 
daß dann zusammengehörende Zugriffe mit dem selben Wert arbeiten und 
nicht evtl. mit verschiedenen, weil sich der Wert zwischendrin geändert 
hat.
Auch bei deinen 16-Bit-Werten wirst du dich nochmal speziell darum 
kümmern müssen, weil da schon ein einzelner Zugriff nicht atomar ist, 
egal ob auf Speicher oder Register.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

(1)
Es ist sinnlos, Register volatile zu machen (zumindest für GCC). GCC hat 
intern überhaupt nicht die Möglichleit, ein Register (GPR) als volatile 
zu markieren. Wer's nicht glaubt lese gcc/rtl.def :-)

(2)
16-Bit-Variablen müssen in geraden GPR-Nummern liegen bzw. anfangen

(3)
Es wird mindestend stdint.h benötigt

(4)
Die Fehler treten in Zeile 95-97 auf. Oben sind 3 Zeilen gepostet. U.U 
fehlt einfach in Zeile 42 irgendwo ne Klammer o.ä.

(5)
Wer sich mit sochen Features nicht auskennt (siehe (2)) dem fliegt der 
Code über kurz oder Lang um die Ohren. Dann suchst die nen Wolf. Oder 
zwei oder drei. Etwa bei Verwendung von STandard-Bibliotheken, 
Interrupts, etc. GCC kann globale Register wegoptimieren . So gesehen 
in GCC 4.x, wo es als tot analysiert wurde (was es im Sinne von C auch 
war, da es asynchron verwendet werden sollte. Da solche Regs jedoch 
nicht volatile sind bzw. das wirkungslos ist, muss man Hacks einfügen, 
die der Code weder hübscher noch besser wartbar, verständlicher oder 
portierbarer machen.

(6)
Die "Optimierung" wird nicht viel bringen. Diese Register sind 
eingeschränkt, was ihren Funktionsumfang angeht. Wenn du zB 42 in ein 
solches Register laden willst, wird die 42 in ein oberes GPR geladen und 
von dort verschoben.

(7)
Wenn der Speicher voll ist, bringt es nix, blindlinks Hacks einzufügen. 
Als erstes muss untersucht werden, wo die Speicherfresser sind. Es ist 
zwecklos eine Variable wie i, die wohl nur eine Laufvariable ist, die eh 
in einem GPR lebt.

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
Noch kein Account? Hier anmelden.