Forum: Mikrocontroller und Digitale Elektronik 16-Bit Mikrocontroller: uchar oder uint?


von Miachael B. (allesklarw)


Lesenswert?

Hallo!

Da mir dieses Forum des Öfteren geholfen hat, wurde es Zeit, dass ich 
mich auch einmal anmelde, um eine Frage stellen zu können.

Ich hoffe meine Frage wurde noch nicht behandelt.



Ich programmiere derzeit einen 16-Bit Mikrocontroller. Aus Gewohnheit 
(um Speicher zu sparen) initialisiere ich Integer-Werte meistens über:

unsigned char i = 0;


Macht es aber bei einem 16-Bit MC nicht mehr Sinn (z.B. aus 
Optimierungsgründen des MCs) einen Integer-Wert einfach mittels

unsigned int i = 0;

zu initialisieren?


Vielen Dank für eure Antworten!!!

von (prx) A. K. (prx)


Lesenswert?

Auf Maschinen mit mindestens 16-Bit Verarbeitung ist "int/unsigned" 
effizienter als kleinere Datentypen. Nicht immer und überall, aber als 
Daumenregel passt es. Ganz besonders bei lokalen Variablen.

Eben deshalb gibt in in stdint.h entsprechende Definitionen:
http://en.wikipedia.org/wiki/Stdint.h#Fastest_minimum-width_integer_types

von Miachael B. (allesklarw)


Lesenswert?

Super. Danke!!!

von MaWin (Gast)


Lesenswert?

> tendentiell

ist das richtige Wort. Denn es hängt vom Befehlssatz und der internen 
Implementation ab. Gerade bei Microcontrollern mit eingebautem Speicher 
ist nämlich nicht zu erwarten, daß sie zum Schreben eines char erst den 
int holen müssen, die alten 8 bit beibehalten, die neuen 8 bit 
einflanschen und dann alle 16 bit zurückschreiben, sondern daß sie 8 bit 
einzeln schreiben können, wie es auch die 68000 Prozessoren konnten.

Umgekehrt kann es bei Prozessoren mit cache der Fall sein, daß nur die 
geholte Datenmenge zählt weil die internen Operationen eh viel schneller 
ablaufen als die fetches.

Beim R8C habe ich z.B. in C den Effekt, daß MANCHMAL 8 bit Operationen 
mehr Code erzeugen, MEISTENS aber 8 und 16 bit gleich viel Code erzeugen 
und nur SELTEN 8 bit weniger Code erzeugt als 16 bit.

von Frank K. (fchk)


Lesenswert?

Das kommt auf den Befehlssatz an.

Auf x86-64 ist es z.B. so, dass 64 Bit Integers effizienter als 32 Bit 
Integers sind, weil auf 32 Bit erst per Prefix OpCode runtergeschaltet 
werden muss. Unter Windows verwendet man daher DWORD_PTR anstelle DWORD, 
sprich ein DWORD in der Größe eines Pointers (64 bittig auf x86-64 und 
32 bittig auf x86).

Wie das bei Deiner Architektur ist, solltest Du selber ausprobieren, 
indem Du vom Compiler ein Assemblerlisting ausgeben lässt. Da siehst Du 
dann, was effizient ist und was nicht.

Ich würde übrigens statt int immer short nehmen, weil int auf vielen 
Plattformen und Compilern auch mal 32 bittig sein kann. short ist 
eindeutiger.

fchk

von ... (Gast)


Lesenswert?

Frank K. schrieb:
> Auf x86-64 ist es z.B. so, dass 64 Bit Integers effizienter als 32 Bit
> Integers sind, weil auf 32 Bit erst per Prefix OpCode runtergeschaltet
> werden muss.

Der Umschaltopcode macht den Kohl nicht fett,
wenn der Cache kleinere Datenmengen (bei 32 Bit die Hälfte von 64 Bit)
schneller bedienen kann und unterm Strich weniger Speicherbandbreite
verbraucht wird.

von (prx) A. K. (prx)


Lesenswert?

MaWin schrieb:

> Denn es hängt vom Befehlssatz und der internen Implementation ab.

Ich weiss, drum oben auch etwas umformuliert. Aber umgekehrt ist "int" 
kaum jemals weniger effizient als kleiner Typen.

> Gerade bei Microcontrollern mit eingebautem Speicher
> ist nämlich nicht zu erwarten, daß sie zum Schreben eines char erst den
> int holen müssen, die alten 8 bit beibehalten, die neuen 8 bit
> einflanschen und dann alle 16 bit zurückschreiben, sondern daß sie 8 bit
> einzeln schreiben können, wie es auch die 68000 Prozessoren konnten.

Das ist nicht der Punkt, Maschinen ohne byteweise Schreibfähigkeit gibt 
es praktisch nicht mehr, egal ob der Speicher intern oder extern ist 
(DSPs vielleicht; da habe ich keinen Überblick).

Der Unterschied liegt erstens in der C Definition, nachdem alle 
Operationen mit Datentypen kleiner "int" so zu behandeln sind, als ob 
sie in "int" gerechnet würden. Das kann zu zusätzlichem Aufwand führen, 
insbesondere bei Maschinen, die eigentlich auch in Registers mit 
kleineren Typen rechnen können.

Zweitens entsteht Zusatzaufwand wenn alles in voller Breite gerechnet 
wird (bei RISCs meist unvermeidlich), wenn ein vom Code direkt 
weiterverwendetes Ergebnis im Register in grösserer Breite vorliegt als 
im Speicher. Dann muss für die Weiterverwendung des Registerinhalts  der 
Inhalt entsprechend abgeschnitten werden. Diese Effekt ist bei lokalen 
Variablen recht bedeutsam.

> Umgekehrt kann es bei Prozessoren mit cache der Fall sein, daß nur die
> geholte Datenmenge zählt weil die internen Operationen eh viel schneller
> ablaufen als die fetches.

Ja, das kann eine gewisse Rollen spielen, wird aber bei einfachen 
Variablen nicht spürbar ins Gewicht fallen. Das spielt eher eine Rolle 
bei Arrays.

von (prx) A. K. (prx)


Lesenswert?

Frank K. schrieb:

> Auf x86-64 ist es z.B. so, dass 64 Bit Integers effizienter als 32 Bit
> Integers sind, weil auf 32 Bit erst per Prefix OpCode runtergeschaltet
> werden muss.

Das ist nicht ganz richtig, weil bei AMD64 die Standardoperationsgrösse 
32-Bit ist und für 64-Bit Operationen per Präfix hochgeschaltet werden 
muss.

> Ich würde übrigens statt int immer short nehmen, weil int auf vielen
> Plattformen und Compilern auch mal 32 bittig sein kann. short ist
> eindeutiger.

Eindeutiger ja, aber weniger effizient. uint8_t ist bei ARM7 insgesamt 
ein kleines bischen effizienter als uint16_t/int16_t - die 
entsprechenden Lade/Speicherbefehle gab es in der ursprünglichen ARM 
Architektur überhaupt nicht und die später hinzu gefügten Befehle haben 
ein kleineres Displacement.

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.