Der springende Punkt ist, dass in C IMMER im größten Datentyp der an der
Operation beteiligten Operanden gerechnet wird, aber nicht kleiner als
int.
D.h. selbst wenn deine Variable ein signed char ist, so wird die
Operation
variable << 8
als eine int Operation ausgeführt. D.h. die 'variable' wird zunächst auf
einen int erweitert.
Da du aber dummerweise ein
1 | static char * biosda = (char*) 0x0400;
|
gemacht hast, hast du es hier mit einem 'char' zu tun. Ob dieser char
nun ein 'signed char' ist oder ein 'unsigned char', dass wissen nur die
Compilerbauer bzw. die Doku zu deinem Compiler.
So etwas macht man nicht!
Man verwendet nicht einfach nur einen 'char', wenn es wichtig ist, ob
dieser char ein Vorzeichen hat oder nicht. Denn das macht einen
Unterschied, wenn aus diesem char ein int geformt wird. In dem einen
Fall findet eine Vorzeichenerweiterung statt (und aus 0xF8 wird dann im
Falle eines 16 Bit int ein 0xFFF8) und im anderen Fall findet die nicht
statt (und aus einem 0xF8 wird ein 16-Bit 0x00F8).
In deinem Fall ist aber dieser Uterschied entscheidend. Denn du willst
in den oberen 8 Bit kein implizites FF stehen haben! Da muss nach wie
vor ein 00 drinnen sein, damit du dann die 0x03 einodern kannst.
Also: gewöhn dich daran. Es gibt 3(!) verschiedene Char-Typen
1 | signed char ein "kleiner" Integer mit Vorzeichen
|
2 | unsigned char ein "kleiner" INteger ohne Vorzeichen
|
3 | char für alles was mit Textverarbeitung zu tun hat
|
Hast du Textverarbeitung?
Nein, hast du nicht. Also ist 'char' der falsche Datentyp. Wenn du es
mit Bytes zu tun hast, dann verwendest du IMMER 'unsigned char'. Tust du
es, dann hast du weniger Probleme.
1 | static unsigned char * biosda = (char*) 0x0400;
|
2 |
|
3 | // wegen little Endian liegt das Low-Byte zuerst im Speicher
|
4 | unsigned short data = ( biosda[1] << 8 ) | biosda[0];
|