Hallo folgendes Problem lässt mich seit Stunden verzweifeln: Meine Ausgangsvarriabel: static char * biosda = (char*) 0x0400; Die Varriabel ist 254 Bytes groß. Bei Offset 0x00 befindet sich ein 2Byte großer Wert. Es sollte eigentlich 0x3F8 (DEC. 1016) herrauskommen. Leider ist das Ergebnis immer f803. Hier meine umwandlung: unsigned short bitemp = (biosda [0x00]<<8) | biosda[0x01]; Ich versteh nicht wieso die 3 immer hinter f8 steht, sie müsste davor stehen. Wieso klappt das nicht?
Schreibst du die Variable selbst rein? Little Endian oder big endian?
Nein, ich schreibe die Varriable nicht selbst rein. Diese liegen auf dem Speicher 0x0400. Und in diesem Fall auf Offset 0x00. Sprich Byte 0 und 1.
>unsigned short bitemp = (biosda [0x00]<<8) | biosda[0x01]; > >Ich versteh nicht wieso die 3 immer hinter f8 steht, sie müsste davor >stehen. Wieso klappt das nicht? Dann mach das doch so: unsigned short bitemp = (biosda [0x01]<<8) | biosda[0x00];
wissenshunger91x3 schrieb: > unsigned short bitemp = (biosda [0x00]<<8) | biosda[0x01]; holger schrieb: > unsigned short bitemp = (biosda [0x01]<<8) | biosda[0x00]; @wissenshunger91x3 Wo ist denn da der Unterschied? wissenshunger91x3 schrieb: > Funktioniert nicht! Es ist ODER Verknüpft. Super Fehlerbeschreibung. Und tolle (falsche) Begründung :-(
Dirk B. schrieb: > wissenshunger91x3 schrieb: >> unsigned short bitemp = (biosda [0x00]<<8) | biosda[0x01]; > > holger schrieb: >> unsigned short bitemp = (biosda [0x01]<<8) | biosda[0x00]; > > @wissenshunger91x3 > Wo ist denn da der Unterschied? > > wissenshunger91x3 schrieb: >> Funktioniert nicht! Es ist ODER Verknüpft. > Super Fehlerbeschreibung. Und tolle (falsche) Begründung :-( Ich weiß zwar net genau was damit gemeind ist, aber selbst wenn ich beide Varriable drehe kommt das selbe Ergebnis rauß.
>Ich weiß zwar net genau was damit gemeind ist, aber selbst wenn ich >beide Varriable drehe kommt das selbe Ergebnis rauß. Wie kontrollierst du das?
Ich starte einfach den Code und somit fragt er den Speicherbereich ab.
wissenshunger91x3 schrieb: > Ich weiß zwar net genau was damit gemeind ist, Funktioniert nicht ist die schlechteste mögliche Fehlerbeschreibung. Und das sind beides Oder-Verknüpfungen. wissenshunger91x3 schrieb: > aber selbst wenn ich > beide Varriable drehe kommt das selbe Ergebnis rauß. Das kann nur sein wenn bei Index 0 und 1 der gleiche Wert steht. Darum nochmal: Wie stellst du das fest? Debuuger, printf (wenn ja, wie?), irgendetwas anderes?
Also mit % d also als Decimal signed integer oder auch mit %p wie Pointer. Aber auch wenn ich es mit %c ausgeben, ich komme nie auf die Dezimal Zahl: 1016
Du kannst nochmal zwei Sachen probieren
1 | static unsigned char * biosda = (char*) 0x0400; // oder uint8_t statt unsigned char |
2 | // oder/und
|
3 | unsigned short bitemp = ((biosda [0x01] & 0xff)<<8) | (biosda[0x00] & 0xff); |
Dann schreib mal was da ausgegeben wird
1 | printf("00: %02x | 01: %02x\n", biosda[0x00], biosda[0x01]); |
wissenshunger91x3 schrieb: > Hier meine umwandlung: > unsigned short bitemp = (biosda [0x00]<<8) | biosda[0x01]; Die wird auch nicht funktionieren. Du must erst deine beiden Teile nach unsigned short casten. Also so: unsigned short bitemp = ((unsigned short)biosda [0x00]<<8) | (unsigned short)biosda[0x01]; Sonst führt der Compiler die verorderung auf 8 bit char aus.
Und was gibt
1 | unsigned short bitemp = ((biosda[0x01] & 0xff)<<8) | (biosda[0x00] & 0xff); |
2 | printf("0000: %04x\n", bitemp ); |
Dirk B. schrieb: > Und was gibtunsigned short bitemp = ((biosda[0x01] & 0xff)<<8) | > (biosda[0x00] & 0xff); > printf("0000: %04x\n", bitemp ); F803
Helmut Lenzen schrieb: > wissenshunger91x3 schrieb: >> Hier meine umwandlung: >> unsigned short bitemp = (biosda [0x00]<<8) | biosda[0x01]; > > Die wird auch nicht funktionieren. Du must erst deine beiden Teile nach > unsigned short casten. > > Also so: > > unsigned short bitemp = ((unsigned short)biosda [0x00]<<8) | (unsigned > short)biosda[0x01]; > > Sonst führt der Compiler die verorderung auf 8 bit char aus. Hilft leider nicht. Kommt zum selben Ergebnis f803.
>Hilft leider nicht. Kommt zum selben Ergebnis f803.
Kann nicht sein. Zum letzten mal: Zeig dein Programm.
Das was ich im ersten Post geschrieben habe ist eig. das Programm. Nur die Ausgabe fehlt.
>Das was ich im ersten Post geschrieben habe ist eig. das Programm.
Ok, reine Zeitverschwendung. Ich bin raus.
wissenshunger91x3 schrieb: > Hilft leider nicht. Kommt zum selben Ergebnis f803. Dann vertausch die beiden Variablen mal
Dirk B. schrieb in Beitrag #3473589: > Dann schreib mal was da ausgegeben wirdprintf("00: %02x | 01: %02x\n", > biosda[0x00], biosda[0x01]); Sehr unfreundlich holger! Dirk B. Schrieb ich ja schon beide ausgangsvarriable und auch die Ergebnisse die Angezeigt werden.
Helmut Lenzen schrieb: > wissenshunger91x3 schrieb: >> Hilft leider nicht. Kommt zum selben Ergebnis f803. > > Dann vertausch die beiden Variablen mal Wie soll ich sie tauschen?
Die Bytes liegen auf einem geschützten Teil der Bios Data Area. Ich kann sich nicht einfach so tauschen.
Dirk B. schrieb: > Dann schreib mal was da ausgegeben wirdprintf("00: %02x | 01: %02x\n", > biosda[0x00], biosda[0x01]); wissenshunger91x3 schrieb: > 00: f8 | 01: 03 Dirk B. schrieb: > Und was gibtunsigned short bitemp = ((biosda[0x01] & 0xff)<<8) | > (biosda[0x00] & 0xff); > printf("0000: %04x\n", bitemp ); wissenshunger91x3 schrieb: > F803 Ok dann noch die letzte Frage: Und was gibt
1 | unsigned short bitemp = ((biosda[0x00] & 0xff)<<8) | (biosda[0x01] & 0xff); |
2 | printf("0000: %04x\n", bitemp ); |
Hast du Copy&Paste gemacht? Mit den Unterschieden in den Indizes, die in der Kommetarzeile nochmal gekennzeichnet sind?
1 | unsigned short bitemp0 = ((biosda[0x00] & 0xff)<<8) | (biosda[0x01] & 0xff); |
2 | unsigned short bitemp1 = ((biosda[0x01] & 0xff)<<8) | (biosda[0x00] & 0xff); |
3 | // ^ da und da ^
|
Sorry, die letzte Varriante funktioniert. Dirseidanke! Aber wieso? Kann man das gewussel ab abkürzen und kann ich genauso vorgehen wenn ich mehr als 2 Bytes auslesen muss? Vielen dank erstmal für DEINE Hilfe!!!
holger schrieb im Beitrag #3473312 vor 4 Stunden > Dann mach das doch so: > > unsigned short bitemp = (biosda [0x01]<<8) | biosda[0x00];
Dirk B. schrieb: > holger schrieb im Beitrag #3473312 vor 4 Stunden >> Dann mach das doch so: >> >> unsigned short bitemp = (biosda [0x01]<<8) | biosda[0x00]; Damit hatte ich angefang! Das funktionierte aber NICHT. Erst mit &0xFF hat es funktioniert.
Ich habe jetzt dort stehen: unsigned short bitemp = ((biosda [0x00])&0xFF) | (biosda [0x01]&0xFF)<<8) Und NUR DAS funzt!
Aus deinem ersten Post: unsigned short bitemp = (biosda [0x00]<<8) | biosda[0x01]; Ergibt laut deiner Aussage 0xF803. >Und NUR DAS funzt! Warum hat das da oben funktioniert? Nur halt mit der falschen Bytereihenfolge. >Aber wieso? Das wird irgendwie an DIR liegen.
Nicht zu vergessen ist das &0xFF ! Erst damit gehts. Nehm ich beides weg gehts nicht mehr. Liegt vll. am Compiler.
Außerdem gehts die ganze Zeit schon!! Nur die Byte reihenfolge stimmt nicht also statt f803 sollte eigentlich immer 3f8 raußkommen!
Also wenn du die Reihenfolge tauschst, aber das &0xFF weglässt, sind die beiden Bytes immer noch falsch rum und erst durch das &0xFF drehen sie sich? Das ist allerdings sehr merkwürdig.
Erst durch 0xFF und jetzt wäre natürlich interessant wieso.
Die Berechnung erfolgt als int. Die Werte aus biosda werden also von (signed) char auf int erweiter. 0xf8 als char) ist aber ein negativer Wert. Darum wird der auf 0xfff8 oder 0xfffffff8 (je nach Bitbreite vom int) erweitert. Die 0x03 bleibt so wie sie ist. Du hast also (0x03 <<8) | 0xfff8 = fffb Beim Ablegen als unsigned short werden dann wieder nur diu untersten 16 Bit genommen.
Dirk B. schrieb: > Die Berechnung erfolgt als int. > Die Werte aus biosda werden also von (signed) char auf int erweiter. > > 0xf8 als char) ist aber ein negativer Wert. Darum wird der auf 0xfff8 > oder 0xfffffff8 (je nach Bitbreite vom int) erweitert. > > Die 0x03 bleibt so wie sie ist. > > Du hast also (0x03 <<8) | 0xfff8 = fffb > > Beim Ablegen als unsigned short werden dann wieder nur diu untersten 16 > Bit genommen. Könntest du mir das noch etwas zerkleinern mit Ergebnise um es richtig zu verstehen?
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]; |
:
Bearbeitet durch User
Karl Heinz schrieb: > Wenn du es mit Bytes zu tun hast, dann verwendest du IMMER 'unsigned > char'. Tust du es, dann hast du weniger Probleme. Richtig. Oder halt gleich uint8_t verwenden, was auf den meisten Systemen auf unsigned char hinauslaufen dürfte.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.