„Byte-Reihenfolge“ – Versionsunterschied
[gesichtete Version] | [gesichtete Version] |
→Vereinbarungen: Adressierung von Bits |
Lexikographie deutlicher; deshalb Ref zu Jürgen Gärtner entfernt |
||
Zeile 23: | Zeile 23: | ||
* Ein Byte innerhalb eines einfachen Datenfelds hat zu dessen Anfangsadresse einen (nicht-negativen) Abstand, der als ''Offset'' bezeichnet wird. |
* Ein Byte innerhalb eines einfachen Datenfelds hat zu dessen Anfangsadresse einen (nicht-negativen) Abstand, der als ''Offset'' bezeichnet wird. |
||
* Betrachtet werden numerische Daten, die im Speicher entsprechend einem Stellenwertsystem dargestellt sind. Bei einem solchen System kommt einer Ziffer neben ihrem Wert als einzelnem Zeichen noch ein (von ihrer Position innerhalb der ganzen Zahl abhängiger) Stellenwert zu, auch „Wertigkeit“ oder „Signifikanz“ genannt. |
* Betrachtet werden numerische Daten, die im Speicher entsprechend einem Stellenwertsystem dargestellt sind. Bei einem solchen System kommt einer Ziffer neben ihrem Wert als einzelnem Zeichen noch ein (von ihrer Position innerhalb der ganzen Zahl abhängiger) Stellenwert zu, auch „Wertigkeit“ oder „Signifikanz“ genannt. |
||
* Die in Handbüchern und unten vorkommenden Notationen <code>1A2B3C4D<Sub>h</Sub></code> oder <code>0x1A2B3C4D</code> bezeichnen einen Zahlwert, und zwar die Zahl 439'041'101 |
* Die in Handbüchern und unten vorkommenden hexadezimalen Notationen <code>1A2B3C4D<Sub>h</Sub></code> oder <code>0x1A2B3C4D</code> bezeichnen einen Zahlwert, und zwar die Zahl 439'041'101, und nicht ihre Darstellung im Speicher, es sei denn man meint die Speicherung <code>1A<Sub>h</Sub>2B<Sub>h</Sub>3C<Sub>h</Sub>4D<Sub>h</Sub></code>. Will man eine andere Art der Speicherung derselben Zahl <code>0x1A2B3C4D</code> ausdrücken, muss man auf andere Notationen, wie <code>4D<Sub>h</Sub>3C<Sub>h</Sub>2B<Sub>h</Sub>1A<Sub>h</Sub></code> oder <code>0x4D,0x3C,0x2B,0x1A</code>, ausweichen. |
||
* Generell multipliziert ein [[Bitweise Verschiebung|Links-Shift]] eine Binärzahl mit einer Zweierpotenz, verschiebt also die Bits in Richtung „Big-End“ (= Richtung [[Bitwertigkeit#MSB-0-Bitnummerierung|most significant bit]]), und ein Rechts-Shift dividiert durch eine solche, verschiebt die Bits in Richtung „Little-End“ (= Richtung [[Bitwertigkeit#LSB-0-Bitnummerierung|least significant bit]]). Die Shift-Operationen induzieren eine eindeutige konsistente Adressierung von den Bytes auf die Bits (s. dazu den Abschnitt [[Bitwertigkeit#Adressierung von Bits|Adressierung von Bits]]). (Die links-rechts-Orientierung bei Shift-Instruktionen ist etwas Anderes und völlig unabhängig von derjenigen bei der Adressierung mit ''links = niedrige'' und ''rechts = hohe'' Adresse.) |
* Generell multipliziert ein [[Bitweise Verschiebung|Links-Shift]] eine Binärzahl mit einer Zweierpotenz, verschiebt also die Bits in Richtung „Big-End“ (= Richtung [[Bitwertigkeit#MSB-0-Bitnummerierung|most significant bit]]), und ein Rechts-Shift dividiert durch eine solche, verschiebt die Bits in Richtung „Little-End“ (= Richtung [[Bitwertigkeit#LSB-0-Bitnummerierung|least significant bit]]). Die Shift-Operationen induzieren eine eindeutige konsistente »Adressierung« von den Bytes auf die Bits (s. dazu den Abschnitt [[Bitwertigkeit#Adressierung von Bits|Adressierung von Bits]]).<ref>Dieser Zusammenhang zwischen Byte-Reihenfolge und Bit-Reihenfolge wurde schon von [[#Cohen|Cohen]] (p. 3) gesehen.</ref> (Die links-rechts-Orientierung bei Shift-Instruktionen ist etwas Anderes und völlig unabhängig von derjenigen bei der Adressierung mit ''links = niedrige'' und ''rechts = hohe'' Adresse.) |
||
Steigt bei einer im Speicher abgelegten Zahl die Wertigkeit einer Stelle mit der wachsenden Adresse, dann ist sie im Little-Endian-Format dargestellt. |
Steigt bei einer im Speicher abgelegten Zahl die Wertigkeit einer Stelle mit der wachsenden Adresse, dann ist sie im Little-Endian-Format dargestellt. |
||
Zeile 30: | Zeile 30: | ||
Fällt bei einer im Speicher abgelegten Zahl die Wertigkeit einer Stelle mit der wachsenden Adresse, dann ist sie im Big-Endian-Format dargestellt. |
Fällt bei einer im Speicher abgelegten Zahl die Wertigkeit einer Stelle mit der wachsenden Adresse, dann ist sie im Big-Endian-Format dargestellt. |
||
Wird bei einem Computersystem eines dieser beiden Formate für die Speicherung ''numerischer''<ref>Der [[Zeichenkette#strcmp|Vergleich von ''Zeichenketten'']] durch Maschineninstruktionen oder die C-Funktionen <code>memcmp()</code> und <code>strcmp()</code> startet auf ''jeder'' Maschine am |
Wird bei einem Computersystem eines dieser beiden Formate für die Speicherung ''numerischer''<ref>Der [[Zeichenkette#strcmp|Vergleich von ''Zeichenketten'']] durch Maschineninstruktionen oder die C-Funktionen <code>memcmp()</code> und <code>strcmp()</code> startet auf ''jeder'' Maschine am ''Anfang''sbuchstaben der Zeichenkette und wertet damit die Stellen niedriger Adresse als höherrangig, agiert also im Big-Endian Stil. Man nennt diese Übertragung der Ordnung von den einzelnen Bytes auf mehrstellige Felder, wenn sie bei der ersten Stelle beginnt, die ''[[lexikographische Ordnung]]''. (S. a. {{cite web|url=http://en.cppreference.com/w/c/string/byte/strncmp |title=strncmp|accessdate=2015-03-26}})<br />Die Erwähnung von Zeichenketten („Strings“) in der Literatur, z. B. [http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html ''Big and Little Endian'' C-style strings] und [http://www.keil.com/support/man/docs/c51/c51_xe.htm ''Byte Ordering''], im Kontext der Endianness beschränkt sich häufig auf die Übertragungsweise.</ref> Felder durchgehalten, so wird das erste als ''Little-Endian-'', das zweite als ''Big-Endian-System'' bezeichnet. |
||
== Beispiel: Speicherung einer Integer-Zahl von 32 Bit in 4 Bytes == |
== Beispiel: Speicherung einer Integer-Zahl von 32 Bit in 4 Bytes == |
||
Zeile 114: | Zeile 114: | ||
== Wichtige Eigenschaften der Darstellungen == |
== Wichtige Eigenschaften der Darstellungen == |
||
Die [[Register (Computer)|Registerbreite]] ist bei den meisten [[Hauptprozessor|CPUs]] normalerweise |
Die [[Register (Computer)|Registerbreite]] ist bei den meisten [[Hauptprozessor|CPUs]] normalerweise gleich oder doppelt so breit wie der [[Bus (Datenverarbeitung)|Datenbus]]. Bei den ersten Mikroprozessoren waren dies nur 4 Bit (später dann lange Zeit 8 Bit). Der Adressbus ist aber bei diesen CPUs wesentlich breiter. Damit ergab sich die Notwendigkeit, Daten mit einem Befehl zu laden oder zu speichern, welche auf mindestens zwei gekoppelte Register verteilt waren. Um die Komplexität der CPU zu verringern (jede einzelne Transistorfunktion war noch teuer) war es einfacher, bei jeder Operation automatisch das niederwertige „Datenhäppchen“ zu laden, während dieser Speicheroperation konnte dann der Befehl weiter dekodiert und gegebenenfalls die weiteren Daten im nächsten Zyklus bearbeitet werden. Bei Großrechnern („main frames“) bestand dieses Problem weniger, da sie damals schon mit Datenbus-Breiten von 16 bis 48 Bit arbeiteten, diese also in einem einzigen Speicherzyklus laden konnten und somit die (Byte)-Reihenfolge keine Rolle spielte. |
||
=== Big-Endian-Format === |
=== Big-Endian-Format === |
||
Zeile 166: | Zeile 166: | ||
! colspan="4" | !! colspan="7" style="text-align:center;" |Little-Endian |
! colspan="4" | !! colspan="7" style="text-align:center;" |Little-Endian |
||
|- style="background:#eef;" |
|- style="background:#eef;" |
||
| colspan="4"| <small>interne Bitfolge</small> ||<code>1110 0101</code>|| ||<code>0100 1100</code> |
| colspan="4"| <small>[[#interne_Bitfolge|interne Bitfolge]]</small> ||<code>1110 0101</code>|| ||<code>0100 1100</code> |
||
| |
| |
||
| <code><span style="border-top:1px solid; padding:0 0.0em;">1110 0101</span> 0100 1100</code> |
| <code><span style="border-top:1px solid; padding:0 0.0em;">1110 0101</span> 0100 1100</code> |
||
Zeile 186: | Zeile 186: | ||
|} |
|} |
||
Besteht das Feld nur aus einem einzelnen Byte (8-Bit-Binärzahl mit oder [[Logische Verschiebung|ohne Vorzeichen]]) oder nur aus Text mit Einzelzeichen (zum Beispiel im Code [[ISO 8859]]), dann unterscheidet sich die Interpretation der 4 Halbbytes bei den beiden Formaten Big- oder Little-Endian nicht. {{Anker| |
Besteht das Feld nur aus einem einzelnen Byte (8-Bit-Binärzahl mit oder [[Logische Verschiebung|ohne Vorzeichen]]) oder nur aus Text mit Einzelzeichen (zum Beispiel im Code [[ISO 8859]]), dann unterscheidet sich die Interpretation der 4 Halbbytes bei den beiden Formaten Big- oder Little-Endian nicht. {{Anker|interne_Bitfolge}}Zwar ist in Little-Endian-Systemen die ''interne Reihenfolge der Bits'' pro Byte genauso umgedreht wie die der Bytes pro Integer (s. [[Bitwertigkeit#Adressierung von Bits]]). {{Anker|Bitschablone}}Die Bitschablone <code>7654 3210</code><ref>die in den Intel-Handbüchern zu finden ist und die mit der internen Reihenfolge der Bits (oder gar mit deren Verdrahtung) rein nichts zu tun hat</ref> ordnet die Bits wie in der üblichen [[Dualsystem|Dualdarstellung]] nach absteigender Wertigkeit und mit der Einerstelle beim Bit 0, also im Big-Endian-Format. Mithin wird im Hexdump die Umordnung der Bits bei einem einzelnen Byte nicht erkennbar. |
||
Besteht das Feld aus mehr als einem Byte, wird die Umkehrung der Reihenfolge der Bytes in Little-Endian-Systemen sichtbar. Ist es beispielsweise eine 16-Bit-Binärzahl, dann |
Besteht das Feld aus mehr als einem Byte, wird die Umkehrung der Reihenfolge der Bytes in Little-Endian-Systemen sichtbar. Ist es beispielsweise eine 16-Bit-Binärzahl, dann wird die Bitfolge in den zwei Bytes durch die lange Bitschablone <code>fedc ba98 7654 3210</code> gerade vertauscht. Zur Verdeutlichung ist in der Tabelle der Inhalt vom ersten der 2 Bytes mit einem Überstrich versehen. |
||
Der Endianness-Typ einer Maschine lässt sich programmtechnisch abgreifen. |
|||
Die Byte-Reihenfolge (Endianness) lässt sich mit einem einfachen Programm testen. |
|||
<syntaxhighlight lang = "C"> |
<syntaxhighlight lang = "C"> |
||
union { |
union { |
||
Zeile 230: | Zeile 230: | ||
== Etymologie == |
== Etymologie == |
||
Die Bezeichnungen gehen auf den [[Satire|satirischen]] Roman [[Gullivers Reisen]] von [[Jonathan Swift]] zurück, in dem die Bewohner des Landes [[Liliput (fiktive Insel)|Liliput]] in zwei verfeindeten Gruppen leben: Die einen schlagen ihre Eier am dicken, „großen“, englisch „big“, Ende auf und werden deshalb als ''Big Ender'' bezeichnet, während die ''Little Ender'' die Eier am spitzen, „kleinen“, englisch „little“ Ende öffnen. |
Die Bezeichnungen gehen auf den [[Satire|satirischen]] Roman [[Gullivers Reisen]] von [[Jonathan Swift]] zurück, in dem die Bewohner des Landes [[Liliput (fiktive Insel)|Liliput]] in zwei verfeindeten Gruppen leben: Die einen schlagen ihre Eier am dicken, „großen“, englisch „big“, Ende auf und werden deshalb als ''Big Ender'' bezeichnet, während die ''Little Ender'' die Eier am spitzen, „kleinen“, englisch „little“ Ende öffnen. Swift spielte damit auf die Abspaltung der englischen Kirche (Spitz-Ender) von der katholischen Kirche (Dick-Ender) an – in Zusammenhang mit der Byte-Reihenfolge wurde dies erstmals 1980 von [[Danny Cohen (Ingenieur)|Danny Cohen]] in dem [[Aprilscherz]]-[[Wissenschaftliche Publikation|Paper]] ''On Holy Wars and a Plea for Peace'' gebracht.<ref>[[#Cohen|Danny Cohen]]: ''On Holy Wars and a Plea for Peace''</ref> |
||
== Weblinks == |
== Weblinks == |
||
⚫ | |||
* Jürgen Gärtner: [http://www.jgae.de/endian.htm ''Little/Big Endian''.] (Philosophisches zum Thema) |
|||
⚫ | |||
* [http://3bc.bertrand-blanc.com/endianness05.pdf White Paper: ''Endianness or Where is Byte 0?''] (PDF, 155 kB, englisch) |
* [http://3bc.bertrand-blanc.com/endianness05.pdf White Paper: ''Endianness or Where is Byte 0?''] (PDF, 155 kB, englisch) |
||
* [http://betterexplained.com/articles/understanding-big-and-little-endian-byte-order/ ''Understanding Big and Little Endian Byte Order''.] (englisch) |
* [http://betterexplained.com/articles/understanding-big-and-little-endian-byte-order/ ''Understanding Big and Little Endian Byte Order''.] (englisch) |
Version vom 13. Mai 2016, 12:08 Uhr
Die Byte-Reihenfolge (englisch byte order oder endianness) bezeichnet in der Computertechnik die Speicherorganisation für einfache Zahlenwerte, in erster Linie die Ablage von ganzzahligen Werten (Integer) im Arbeitsspeicher.
Die ersten Rechnerarchitekturen haben die Darstellung von mehrstelligen Zahlen aus dem Alltag entsprechend der Konvention des Stellenwertsystems übernommen, zunächst für dezimal, dann auch für binär dargestellte Zahlen. In dieser Konvention beginnt die Notation einer Zahl mit der Ziffer an der höchstwertigen Stelle. Addition, Subtraktion und Multiplikation beginnen aber mit der niedrigstwertigen Ziffer, der Einerstelle.
Solange man innerhalb ähnlicher Rechnerarchitekturen blieb, musste man sich nicht um die Endianness kümmern, sie entsprach ja der gewohnten. Da die genannten drei mathematischen Grundfunktionen jedoch einen Maschinenzyklus früher starten können, wenn man die Bitreihenfolge umkehrt, haben in der Folge einige Hersteller ein entsprechendes Architekturprinzip erstellt. Das heißt: die Einerstelle wird an die Anfangsadresse gelegt, und die 3 Algorithmen schreiten nach rechts in die höheren Stellen und Adressen fort. Diese Abweichung vom Gewohnten machte die Begriffsbildung Endianness erforderlich.
- Bei Big-Endian (wörtlich „Groß-Ender“, siehe auch Abschnitt Etymologie) wird das höchstwertige Byte zuerst gespeichert, das heißt an der kleinsten Speicheradresse. Allgemein bedeutet der Begriff, dass bei zusammengesetzten Daten die größtwertige (höchstrangige) Komponente zuerst genannt wird, wie etwa bei der deutschen Schreibweise der Uhrzeit: Stunde:Minute:Sekunde.
- Bei Little-Endian (wörtlich „Klein-Ender“) wird dagegen das kleinstwertige Byte an der Anfangsadresse gespeichert beziehungsweise die kleinstwertige Komponente zuerst genannt, wie bei der herkömmlichen deutschen Datumsschreibweise: Tag.Monat.Jahr.
Die Begriffe Big-Endian und Little-Endian bezeichnen also dasjenige Ende der Darstellung, das an erster Stelle notiert beziehungsweise an der kleinsten Adresse gespeichert wird. Da letztere Adresse auch in aller Regel das ganze (mehrstellige) Feld adressiert, wären die Bezeichnungen „Big-Startian“ und „Little-Startian“ noch treffender, weil das Feld an der Stelle, um die es geht, nicht endet, sondern startet.
Im Sprachgebrauch werden die beiden Varianten in der Computertechnik oft auch nach den Herstellern von Mikroprozessoren benannt, die die jeweilige Variante in mehreren Prozessorfamilien verwenden beziehungsweise verwendet haben: „Motorola-Format“ steht für Big-Endian, während „Intel-Format“ für Little-Endian steht.
Werden Daten bitweise seriell übertragen, so ist auch die Bit-Reihenfolge festzulegen. Logisch erscheint Big-Endian-Byte-Reihenfolge, wenn das höchstwertige Bit eines Bytes zuerst übertragen wird (etwa I²C), und entsprechend umgekehrt (etwa RS-232). Bisweilen sieht man auch umgekehrte Zuordnungen, etwa bei Bildwiederholspeichern.
Vereinbarungen
Folgende Aussagen, über die in der Literatur hochgradiger Konsens besteht, seien als Ausgangsbasis für die Diskussion und Definition der Sachverhalte explizit gemacht:
- Der Arbeitsspeicher kennt eine kleinste addressierbare Einheit, auch „Speicherstelle“ genannt. In diesem Artikel sei sie exemplarisch das Byte. Es besteht aus 8 Bits und sein Inhalt wird in diesem Artikel vorwiegend mit zwei hexadezimalen Ziffern angegeben, wo jede Ziffer für 4 Bits entsprechend einem Halbbyte steht. Die kleinste addressierbare Einheit könnte aber auch aus einer anderen Anzahl von Bits bestehen, oder, wenn die Maschine im Dezimalsystem rechnet, eine Dezimalziffer beherbergen.
- Die (Byte-)Adressen des Arbeitsspeichers sind nicht-negative ganze Zahlen.
- Ein (einfaches) Datenfeld wird im Arbeitsspeicher in einem zusammenhängenden Speicherbereich (einer lückenlosen Folge von Adressen) abgelegt, der eine Anfangs-(Byte-)adresse und eine (Byte-)Länge hat.
- Die Maschinenbefehle adressieren ein Datenfeld über seine Anfangsadresse.[1] Ganz analog spielt in Assemblersprachen und in höheren Programmiersprachen die Anfangsadresse die Rolle eines Zeigers zum Datenfeld.
- Das Byte an der Anfangsadresse wird häufig als das linke, das an der Endadresse als das rechte Byte bezeichnet. An diese Orientierung halten sich horizontale graphische Darstellungen von Datenfeldern sehr häufig, aber nicht immer.
- Ein Byte innerhalb eines einfachen Datenfelds hat zu dessen Anfangsadresse einen (nicht-negativen) Abstand, der als Offset bezeichnet wird.
- Betrachtet werden numerische Daten, die im Speicher entsprechend einem Stellenwertsystem dargestellt sind. Bei einem solchen System kommt einer Ziffer neben ihrem Wert als einzelnem Zeichen noch ein (von ihrer Position innerhalb der ganzen Zahl abhängiger) Stellenwert zu, auch „Wertigkeit“ oder „Signifikanz“ genannt.
- Die in Handbüchern und unten vorkommenden hexadezimalen Notationen
1A2B3C4Dh
oder0x1A2B3C4D
bezeichnen einen Zahlwert, und zwar die Zahl 439'041'101, und nicht ihre Darstellung im Speicher, es sei denn man meint die Speicherung1Ah2Bh3Ch4Dh
. Will man eine andere Art der Speicherung derselben Zahl0x1A2B3C4D
ausdrücken, muss man auf andere Notationen, wie4Dh3Ch2Bh1Ah
oder0x4D,0x3C,0x2B,0x1A
, ausweichen. - Generell multipliziert ein Links-Shift eine Binärzahl mit einer Zweierpotenz, verschiebt also die Bits in Richtung „Big-End“ (= Richtung most significant bit), und ein Rechts-Shift dividiert durch eine solche, verschiebt die Bits in Richtung „Little-End“ (= Richtung least significant bit). Die Shift-Operationen induzieren eine eindeutige konsistente »Adressierung« von den Bytes auf die Bits (s. dazu den Abschnitt Adressierung von Bits).[2] (Die links-rechts-Orientierung bei Shift-Instruktionen ist etwas Anderes und völlig unabhängig von derjenigen bei der Adressierung mit links = niedrige und rechts = hohe Adresse.)
Steigt bei einer im Speicher abgelegten Zahl die Wertigkeit einer Stelle mit der wachsenden Adresse, dann ist sie im Little-Endian-Format dargestellt.
Fällt bei einer im Speicher abgelegten Zahl die Wertigkeit einer Stelle mit der wachsenden Adresse, dann ist sie im Big-Endian-Format dargestellt.
Wird bei einem Computersystem eines dieser beiden Formate für die Speicherung numerischer[3] Felder durchgehalten, so wird das erste als Little-Endian-, das zweite als Big-Endian-System bezeichnet.
Beispiel: Speicherung einer Integer-Zahl von 32 Bit in 4 Bytes
Big Endian |
Little Endian |
Middle Endian |
Mixed Endian | |||||
---|---|---|---|---|---|---|---|---|
Adresse | Hex | Dez | Hex | Dez | Hex | Dez | Hex | Dez |
10000 | 1A |
26
|
4D |
77
|
2B |
43
|
3C |
60
|
10001 | 2B |
43
|
3C |
60
|
1A |
26
|
4D |
77
|
10002 | 3C |
60
|
2B |
43
|
4D |
77
|
1A |
26
|
10003 | 4D |
77
|
1A |
26
|
3C |
60
|
2B |
43
|
Im Beispiel wird die Ganzzahl 439'041'101 (Vierhundertneununddreißig Millionen Einundvierzig Tausend Einhundert und Eins) als 32-Bit-Integer-Wert gespeichert (hexadezimal: 1A2B3C4Dh
). Die Speicherung erfolgt in vier Bytes ab einer angenommenen Speicheradresse von 10000
.
Big Endian speichert die Beispielzahl in der Reihenfolge 1A 2B 3C 4D = 1Ah2Bh3Ch4Dh
.
Dagegen speichert Little Endian die Bytes in der umgekehrten Reihenfolge 4D 3C 2B 1A = 4Dh3Ch2Bh1Ah
.
Einige ältere Systeme (z. B. PDP-11) speichern die Daten auch in der Reihenfolge 3C 4D 1A 2B = 3Ch4Dh1Ah2Bh
oder auch 2B 1A 4D 3C = 2Bh1Ah4Dh3Ch
. Dies wird als Middle Endian bezeichnet.
Einige Systeme speichern sowohl Big Endian wie Little Endian, was als Mixed Endian bezeichnet wird.
Hardware-Beispiele
Das Format Little Endian wurde ursprünglich bei dem Prozessor 6502, der NEC-V800-Reihe, PICmicro oder den Intel-x86-Prozessoren verwendet. Dagegen wurde das Big-Endian-Format beispielsweise bei der Motorola-6800- sowie der Motorola-68000- beziehungsweise -Coldfire-Familie, den Prozessoren der System-z- und Sun-SPARC-CPUs und dem PowerPC eingesetzt. Letzterer kann jedoch bei einigen Modellen auch auf Little-Endian umgeschaltet werden. Die von Hewlett-Packard und Intel gemeinsam entwickelte IA-64-Architektur beherrscht ebenfalls beide Byte-Reihenfolgen, wodurch die Portierung von Betriebssystemen, insbesondere HP-UX (Big Endian) und Windows (Little Endian), auf diese Architektur erleichtert wird.
Reihenfolge der Ziffern innerhalb von Zahlen in der Sprache
Auch die gewöhnliche Darstellung von (Dezimal-)Zahlen ist – im Sinne der Leserichtung der meisten europäischen Sprachen von links nach rechts – Big Endian. Dies kommt jedoch dadurch zustande, dass die Ziffernreihenfolge der indisch-arabischen Zahlen bei den Schriften Mitteleuropas beibehalten wurde. Im Arabischen, das sich von rechts nach links liest, werden die Zahlen gleich geschrieben, das heißt, für Zahlen unter 100 werden sie als „Little Endian“ gelesen (für Zahlen ab 100 werden sie Big-Endian gelesen). Auch im Deutschen werden die Zahlen von 13 bis 99 little-endian ausgesprochen: „Ein-und-Zwanzig“. Die Eins als weniger wertige Stelle wird zuerst gesprochen (auch in anderen Sprachen gibt es diese Reihenfolge).
Ein Beispiel für Dezimalzahlen: In der gebräuchlichsten Darstellung (Big Endian) wird die Dezimalzahl Eintausend-zweihundert-dreißig als „1230“ dargestellt, wobei die „1“ die Wertigkeit 1000, die „2“ die Wertigkeit 100 hat und die „3“ die Wertigkeit 10 erhält. In der „Little-Endian“-Darstellung ist es umgekehrt, so dass die Darstellung der Zahl „0321“ wäre (ausgesprochen vielleicht „Dreißig-Zweihundert-Eintausend“).
Kontexte des Byte-Reihenfolge-Problems
Das Problem der Byte-Reihenfolge betrifft solche Datentypen, die aus mehreren Byte zusammengesetzt sind und vom jeweiligen Prozessor direkt unterstützt werden, also hauptsächlich Ganzzahl- und Gleitkommatypen, sowie Datentypen, die vom Prozessor effektiv als solche interne Datentypen behandelt werden, zum Beispiel UTF-16. Um dieses Problem bei Unicode-Zeichen zu umgehen, wird oft eine Bytereihenfolge-Markierung (BOM) benutzt. In einem Hex-Editor sieht ein Text folgendermaßen aus:
44 00 69 00 65 00 |D i e | = UTF-16LE / UCS-2LE; BOM am Dateianfang = FF FE 00 44 00 69 00 65 | D i e| = UTF-16BE / UCS-2BE; BOM am Dateianfang = FE FF
Plattformübergreifende Darstellung von Zahlen
Um einen fehlerfreien Datenaustausch zwischen Computern verschiedener Plattformen zu ermöglichen, ist bei Netzwerkprotokollen immer die Byte-Reihenfolge festgeschrieben. Diese wird als „Network Byte Order“ bezeichnet. Die natürliche Byte-Reihenfolge des Systems wird demgegenüber als „Host Byte Order“ bezeichnet. Arbeitet das System nicht mit dieser Byte-Reihenfolge, so muss diese im Netzwerktreiber beziehungsweise zum Teil im Anwendungsprogramm entsprechend umgewandelt werden.
Im Falle des heute vornehmlich verbreiteten Internetprotokoll-Satzes entspricht die Network Byte Order dem Big-Endian-Format. Es existieren jedoch noch immer Protokolle, die eine andere Byte-Reihenfolge verwenden.
In der auf den meisten Betriebssystemen angebotenen BSD-IP-Socket-API existieren zur Umwandlung der Byte-Reihenfolge vier Funktionen:
Name | Datentyp | Bedeutung |
---|---|---|
htonl() |
long (32 bit) | Host-to-network-Umwandlung |
htons() |
short (16 bit) | Host-to-network-Umwandlung |
ntohl() |
long (32 bit) | Network-to-host-Umwandlung |
ntohs() |
short (16 bit) | Network-to-host-Umwandlung |
Auf Big-Endian-Maschinen sind diese Funktionen im Falle des Internetprotokolls wirkungslos, da Host- und Network-Byteorder identisch sind. Es empfiehlt sich jedoch dennoch stets der Gebrauch dieser Funktionen, da sich der Quellcode dadurch auch auf andere Systeme übertragen lässt. Es existieren in dieser API jedoch keine standardisierten Funktionen zur Umwandlung von 64-Bit-Zahlen, da diese bei der Entstehung des Standards noch nicht verbreitet waren.
Byte-Order-Probleme können auch beim Austausch von Dateien sowie zum Teil beim Austausch von Datenträgern zwischen verschiedenen Plattformen auftreten. Hier muss entweder durch eindeutige Definition des entsprechenden Dateiformats beziehungsweise Dateisystems oder durch einen Kompatibilitätsmodus, der während des Ladens eine Erkennung und eventuelle Umwandlung durchführt, Abhilfe geschaffen werden.
Scherzhaft wird das Problem verschiedener Endianness unterschiedlicher Architekturen auch oft als NUXI-Problem bezeichnet: Wenn das Wort UNIX in zwei Zwei-Byte-Words (zwei 16-Bit-Register für „UN“ und „IX“) gespeichert wird, liegt es in einem Big-Endian-System als „UNIX“ im Speicher, in einem Little-Endian-System dagegen wegen der Vertauschung der Byte in jedem Wort als „NUXI“ (auf 32-Bit Systemen stünde dagegen „XINU“ in einem einzelnen 32-Bit-Register).
Wichtige Eigenschaften der Darstellungen
Die Registerbreite ist bei den meisten CPUs normalerweise gleich oder doppelt so breit wie der Datenbus. Bei den ersten Mikroprozessoren waren dies nur 4 Bit (später dann lange Zeit 8 Bit). Der Adressbus ist aber bei diesen CPUs wesentlich breiter. Damit ergab sich die Notwendigkeit, Daten mit einem Befehl zu laden oder zu speichern, welche auf mindestens zwei gekoppelte Register verteilt waren. Um die Komplexität der CPU zu verringern (jede einzelne Transistorfunktion war noch teuer) war es einfacher, bei jeder Operation automatisch das niederwertige „Datenhäppchen“ zu laden, während dieser Speicheroperation konnte dann der Befehl weiter dekodiert und gegebenenfalls die weiteren Daten im nächsten Zyklus bearbeitet werden. Bei Großrechnern („main frames“) bestand dieses Problem weniger, da sie damals schon mit Datenbus-Breiten von 16 bis 48 Bit arbeiteten, diese also in einem einzigen Speicherzyklus laden konnten und somit die (Byte)-Reihenfolge keine Rolle spielte.
Big-Endian-Format
- Da die Maschineninstruktionen die Operanden bei ihrer kleinsten Adresse ansprechen, muss bei Operationen, deren Algorithmus an der kleinstwertigen Stelle beginnt, auf diese durch eine Erhöhung der Anfangsadresse um die Operandenlänge–1 positioniert werden. Somit ist Addieren, Subtrahieren und Multiplizieren geringfügig aufwendiger.
- Dividieren und Vergleichen beginnen dagegen beim höchstwertigen Byte, sind deshalb marginal einfacher.
- Dieselben Vergleichsoperationen können zum Vergleichen von (vorzeichenlosen) Big-Endian-Zahlen wie von kurzen Texten (2, 4 oder 8 Byte lang) genommen werden, da beide lexikographisch sortiert werden.
- Zum Vergleichen von Zeichenketten gibt es beim Großrechnersystem IBM/370 den Maschinenbefehl
CLCL
(Compare Logical Character Long) mit zwei (verschieden und beliebig) langen Speicheroperanden, der die lexikographische Ordnung implementiert.[4] - Im Big-Endian-Format sind Hexdumps von Zahlen leichter lesbar, da die Reihenfolge der Ziffern die gleiche ist wie in der üblichen Schreibweise des Stellenwertsystems.
Little-Endian-Format
- Da die Maschineninstruktionen die Operanden bei ihrer kleinsten Adresse ansprechen, entfällt bei Operationen, deren Algorithmus an der kleinstwertigen Stelle beginnt, so bei Addition, Subtraktion und Multiplikation, das initiale Inkrementieren mit der Operandenlänge. Diese Operationen sind somit geringfügig einfacher in der Hardware zu implementieren.
- Um auf einer Little-Endian-Maschine eine Zwei-Byte-Zahl in eine Vier-Byte-Zahl zu verwandeln, müssen lediglich zwei mit Null gefüllte Bytes am Ende angefügt werden, ohne dass sich die Speicheradresse ändert. Auf einer Big-Endian-Maschine muss der Wert zuvor im Speicher um zwei Bytes verschoben werden. Auch die umgekehrte Umwandlung gestaltet sich einfacher. Auf einer Little-Endian-Maschine werden einfach die höherwertigen Byte verworfen, ohne dass sich die Speicheradresse ändert.
- Dagegen ist die Implementierung von Operationen wie der Division, deren Algorithmus an der höchstwertigen Stelle beginnt, marginal aufwendiger.
- Maschinenbefehle für das lexikographische Vergleichen von langen Wörtern fehlen bei manchen Maschinen und müssen durch Unterprogramme, wie
memcmp()
[5], ersetzt werden.
Beispiel für eine dezimale Little-Endian-Addition:
717 + 0452 ---- 7523 ====
(Probe: 717+2540=3257
)
Beispiel: Interpretation eines Hexdumps
Das folgende Beispiel zeigt, wie zwei aufeinander folgende Bytes (4 Halbbytes) in einem Hexdump mit dem lesbaren hexadezimalen Inhalt a732
zu interpretieren sind.
Hex- dump |
2 vorzeichenlose 8-Bit Binärzahlen |
1 vorzeichenlose 16-Bit Binärzahl | ||||||||
Bytes | Text | Byte0: Bits | dez | Byte1: Bits | dez | Bits | hex | dez | ||
Offset | 0 |
1
|
0123 4567 |
0123 4567 |
0123 4567 89ab cdef
|
|||||
Big-Endian | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
Wert | a7 |
32
|
§2
|
1010 0111 |
167
|
0011 0010 |
50
|
1010 0111 0011 0010
|
a732
|
42802
|
Little-Endian | ||||||||||
interne Bitfolge | 1110 0101 |
0100 1100
|
1110 0101 0100 1100
|
|||||||
Bitschablone | 7654 3210 |
7654 3210
|
fedc ba98 7654 3210
|
|||||||
Wert | a7 |
32
|
§2
|
1010 0111 |
167
|
0011 0010 |
50
|
0011 0010 1010 0111
|
32a7
|
12967
|
Besteht das Feld nur aus einem einzelnen Byte (8-Bit-Binärzahl mit oder ohne Vorzeichen) oder nur aus Text mit Einzelzeichen (zum Beispiel im Code ISO 8859), dann unterscheidet sich die Interpretation der 4 Halbbytes bei den beiden Formaten Big- oder Little-Endian nicht. Zwar ist in Little-Endian-Systemen die interne Reihenfolge der Bits pro Byte genauso umgedreht wie die der Bytes pro Integer (s. Bitwertigkeit#Adressierung von Bits). Die Bitschablone 7654 3210
[6] ordnet die Bits wie in der üblichen Dualdarstellung nach absteigender Wertigkeit und mit der Einerstelle beim Bit 0, also im Big-Endian-Format. Mithin wird im Hexdump die Umordnung der Bits bei einem einzelnen Byte nicht erkennbar.
Besteht das Feld aus mehr als einem Byte, wird die Umkehrung der Reihenfolge der Bytes in Little-Endian-Systemen sichtbar. Ist es beispielsweise eine 16-Bit-Binärzahl, dann wird die Bitfolge in den zwei Bytes durch die lange Bitschablone fedc ba98 7654 3210
gerade vertauscht. Zur Verdeutlichung ist in der Tabelle der Inhalt vom ersten der 2 Bytes mit einem Überstrich versehen.
Der Endianness-Typ einer Maschine lässt sich programmtechnisch abgreifen.
union {
unsigned short shortVar;
unsigned char charVar[2];
} test_endianness;
test_endianness.shortVar = 1;
if (test_endianness.charVar[0]) {
// little-endian-Maschine
}
else {
// big-endian-Maschine
}
Viele programmtechnische Einzelheiten betreffend Endianness finden sich in den Abschnitten zur Programmierung in C und C++ im Artikel Bitkette.
Verwendung
Big-Endian
Big-Endian verwenden Mainframe-Systeme (z. B. IBM-Mainframe) sowie MIPS-, SPARC-, PowerPC-, Motorola 6800/68k-, Atmel AVR32-[7] und TMS9900-Prozessoren. Alpha-Prozessoren lassen sich in diesem Modus betreiben, dies ist jedoch unüblich.
Little-Endian
Heutige PC-Systeme (x86-kompatible) verwenden Little-Endian. Weitere sind Alpha, Altera Nios, Atmel AVR, manche SH3/SH4-Systeme oder VAX.
Dies sind sogenannte True-little-endian-Systeme. Diese Bezeichnung dient zur Unterscheidung von Architekturen, wie manche PowerPC-Varianten (u. a. 603, 740, 750), die als Little-Endian-Systeme konfiguriert werden können (s. u. Bi-Endian) und aus der Sicht des laufenden Programms dann Little-Endian verwenden, Werte im Speicher jedoch weiterhin im Big-Endian-Format ablegen. Bei Lade- und Speicheroperationen wird die Darstellung implizit umgewandelt. Diese Systeme sind keine True-little-endian-Systeme. Bei der Softwareerstellung für diese Systeme muss dies gegebenenfalls berücksichtigt werden, zum Beispiel bei der Treiber-Programmierung.
Mischvarianten (Bi-Endian)
Es existieren Prozessoren, zum Beispiel bestimmte MIPS-Varianten und PowerPC, sowie alle Alpha-Prozessoren, die zwischen Little Endian und Big Endian umschaltbar sind. Auch ARM-Prozessoren (inkl. des Intel XScales) können sowohl mit Little, als auch mit Big Endian betrieben werden.
Dateiformate
Die typische Verwendung einer Byte-Reihenfolge in einer Prozessorarchitektur zur Ablage von Werten im Arbeitsspeicher hat Einfluss auf die Byte-Reihenfolge von Werten im Sekundärspeicher (oft Festplatten). Bei der Neuerstellung von Dateiformaten wurde die Byte-Reihenfolge der Zahlenwerte so gelegt, dass sie beim Speichern und Zurückladen vom Sekundärspeicher ohne Wandlung auskommen. Mittels Speichervirtualisierung können Daten auf dem Sekundärspeicher sogar direkt vom Programm angesprochen werden.
Bedeutsam ist dies für Containerformate mit einer allgemeinen Strukturdefinition. So wurde das Interchange File Format (IFF) für Amiga-Programme entworfen, und entsprechend diesem Motorola-68000-Prozessor wurden die Vier-Byte-Chunk-Längen im Motorola-Format/Big-Endian abgelegt. Auf dem ebenfalls mit Motorola-Prozessoren arbeitenden Macintosh-Rechnern wurde dieses unter anderem für das Audioformat AIFF übernommen.
Bei der Übernahme zur Windows-Plattform auf Intel Prozessoren wurden die Chunk-Längen umdefiniert auf Vier-Byte Intel-Format/Little-Endian und das neue allgemeine Containerformat als Resource Interchange File Format (RIFF) bezeichnet. Dieses RIFF-Dateiformat ist die Grundlage verbreiteter Dateiformate wie RIFF WAVE (*.wav-Dateien) für Audio und Audio Video Interleave (*.avi-Dateien) für Video.
Auch bei Dateiformaten ist es möglich, eine Definition zu entwickeln, die beide Byte-Reihenfolgen der Prozessorarchitekturen einschließt. Bei TIFF-Dateien (Tagged Image File Format) steht in den ersten zwei Bytes der Datei entweder II
oder MM
und bezieht sich damit auf die typischen Bezeichnungen der Byte-Reihenfolge: II
für Intel-Format (Little-Endian) und MM
für Motorola-Format (Big-Endian). Nachfolgende Längen- und Offset-Werte in der Datei werden dann entsprechend kodiert.
Etymologie
Die Bezeichnungen gehen auf den satirischen Roman Gullivers Reisen von Jonathan Swift zurück, in dem die Bewohner des Landes Liliput in zwei verfeindeten Gruppen leben: Die einen schlagen ihre Eier am dicken, „großen“, englisch „big“, Ende auf und werden deshalb als Big Ender bezeichnet, während die Little Ender die Eier am spitzen, „kleinen“, englisch „little“ Ende öffnen. Swift spielte damit auf die Abspaltung der englischen Kirche (Spitz-Ender) von der katholischen Kirche (Dick-Ender) an – in Zusammenhang mit der Byte-Reihenfolge wurde dies erstmals 1980 von Danny Cohen in dem Aprilscherz-Paper On Holy Wars and a Plea for Peace gebracht.[8]
Weblinks
- Danny Cohen: Internet Engineering Note 137: On Holy Wars and a Plea for Peace. IETF, 1. April 1980. (englisch)
- White Paper: Endianness or Where is Byte 0? (PDF, 155 kB, englisch)
- Understanding Big and Little Endian Byte Order. (englisch)
Einzelnachweise und Anmerkungen
- ↑ Dies gilt vor allem für Maschinen, bei denen die Länge der Operanden im Maschinenbefehl codiert ist.
Nicht in dieses Schema passen Maschinen wie die IBM 1401, bei der sogenannte „Wortmarken“ im Speicher die Ausdehnung der Speicheroperanden bestimmen. Solche Maschinen können – je nach Maschinenbefehl – ein aus (mehreren zusammenhängenden Speicherstellen bestehendes) Feld an seiner niedrigen oder seiner hohen Adresse ansprechen und zum anderen Ende hin abarbeiten; so adressiert beispielsweise der Addieren-Befehl der IBM 1401 die Operanden an der Einerstelle (bei dieser Maschine an der hohen Adresse) und arbeitet sich zur Wortmarke vor. Beim Dividieren-Befehl wird der Dividend an der höchstwertigen Stelle (der niedrigen Adresse) und der Divisor an der Einerstelle angesprochen. IBM 1410 Principles of Operation. S. 9. Abgerufen am 3. November 2014. - ↑ Dieser Zusammenhang zwischen Byte-Reihenfolge und Bit-Reihenfolge wurde schon von Cohen (p. 3) gesehen.
- ↑ Der Vergleich von Zeichenketten durch Maschineninstruktionen oder die C-Funktionen
memcmp()
undstrcmp()
startet auf jeder Maschine am Anfangsbuchstaben der Zeichenkette und wertet damit die Stellen niedriger Adresse als höherrangig, agiert also im Big-Endian Stil. Man nennt diese Übertragung der Ordnung von den einzelnen Bytes auf mehrstellige Felder, wenn sie bei der ersten Stelle beginnt, die lexikographische Ordnung. (S. a. strncmp. Abgerufen am 26. März 2015. )
Die Erwähnung von Zeichenketten („Strings“) in der Literatur, z. B. Big and Little Endian C-style strings und Byte Ordering, im Kontext der Endianness beschränkt sich häufig auf die Übertragungsweise. - ↑ Damit der potientiell sehr viele Maschinenzyklen umfassende Befehl den Hauptprozessor nicht monopolisiert, ist er unterbrechbar konzipiert und kann nach einem Hardwareinterrupt an der Stelle fortgesetzt werden, an der er unterbrochen worden ist. (Siehe ESA/390 principles of operation, chapter 7-44 General Instructions SA22-7201-08 ESA/390 Principles of Operation. Abgerufen am 25. Juni 2014. )
- ↑ memcmp. en.cppreference.com, abgerufen am 6. März 2014.
- ↑ die in den Intel-Handbüchern zu finden ist und die mit der internen Reihenfolge der Bits (oder gar mit deren Verdrahtung) rein nichts zu tun hat
- ↑ AVR32 Architecture Document. (PDF; 5,1 MB) Atmel, November 2007
- ↑ Danny Cohen: On Holy Wars and a Plea for Peace