Endianness

HistoryEdit

Många historiska och existerande processorer använder en big-endian minnesrepresentation, antingen uteslutande eller som ett designalternativ. Big-endian minnesrepresentation kallas vanligen för nätverksordning, som används i Internetprotokollsviten. Andra processortyper använder little-endian minnesrepresentation; andra använder ännu ett annat system som kallas ”middle-endian”, ”mixed-endian” eller ”PDP-11-endian”.

BIBM System/360 använder big-endian byteordning, liksom dess efterföljare System/370, ESA/390 och z/Architecture. PDP-10 använder också big-endian-adressering för byteorienterade instruktioner. Minidatorn IBM Series/1 använder också big-endian byteordning.

Hantering av data med olika endianness kallas ibland för NUXI-problemet. Denna terminologi anspelar på de byteordningskonflikter som man stötte på när man anpassade UNIX, som kördes på den blandade-endianen PDP-11, till en big-endian IBM Series/1-dator. Unix var ett av de första systemen som gjorde det möjligt att kompilera samma kod för plattformar med olika interna representationer. Ett av de första programmen som konverterades skulle skriva ut Unix, men på Series/1 skrev det ut nUxi i stället.

Datapoint 2200 använder enkel bit-seriell logik med little-endian för att underlätta carry propagation. När Intel utvecklade 8008-mikroprocessorn för Datapoint använde de little-endian för att uppnå kompatibilitet. Men eftersom Intel inte kunde leverera 8008 i tid använde Datapoint en motsvarighet till en integration i medelstor skala, men little-endianness bibehölls i de flesta av Intels konstruktioner, inklusive MCS-48 och 8086 och dess x86-efterföljare. DEC Alpha, Atmel AVR, VAX, MOS Technology 6502-familjen (inklusive Western Design Center 65802 och 65C816), Zilog Z80 (inklusive Z180 och eZ80), Altera Nios II och många andra processorer och processorfamiljer är också little-endian.

Motorola 6800 / 6801, 6809 och 68000-seriens processorer använde sig av big-endian-format.

Intel 8051 förväntar sig i motsats till andra Intel-processorer 16-bitars adresser för LJMP och LCALL i big-endian-format; xCALL-instruktionerna lagrar dock returadressen på stacken i little-endian-format.

SPARC använde sig historiskt sett av big-endian fram till version 9, som är bi-endian; på motsvarande sätt var de tidiga IBM POWER-processorerna big-endian, men PowerPC- och Power ISA-avkommanterna är nu bi-endian. ARM-arkitekturen var little-endian före version 3 då den blev bi-endian.

Nuvarande arkitekturerRedigera

Intel x86- och AMD64/ x86-64-serier av processorer använder det little-endian-formatet. Andra arkitekturer för instruktionsuppsättningar som följer denna konvention och endast tillåter little-endian-läge är bland annat Nios II, Andes Technology NDS32 och Qualcomm Hexagon.

Vissa arkitekturer för instruktionsuppsättningar gör det möjligt att köra programvara av endera endiannessättet på en bi-endian-arkitektur. Detta inkluderar ARM AArch64, C-Sky, Power ISA och RISC-V.

Enbart big-endian-arkitekturer inkluderar IBM z/Architecture, Freescale ColdFire (som är baserad på Motorola 68000-serien), Atmel AVR32 och OpenRISC. Operativsystemen IBM AIX och Oracle Solaris på bi-endian Power ISA och SPARC körs i big-endian-läge; vissa distributioner av Linux på Power har övergått till little-endian-läge.

Bi-endiannessEdit

Vissa arkitekturer (inklusive ARM version 3 och senare, PowerPC, Alpha, SPARC V9, MIPS, PA-RISC, SuperH SH-4 och IA-64) har en inställning som gör det möjligt att växla mellan endianness i datahämtning och lagring, instruktionshämtning eller båda. Denna funktion kan förbättra prestandan eller förenkla logiken i nätverksenheter och programvara. Ordet bi-endian, när det gäller hårdvara, betecknar maskinens förmåga att beräkna eller överföra data i båda de endianska formaten.

Många av dessa arkitekturer kan växlas via mjukvara så att de som standard har ett visst endianskt format (vilket vanligen görs när datorn startas upp); på vissa system väljs dock standard-endianismen av hårdvara på moderkortet och kan inte ändras via mjukvara (t.ex.t.ex. Alpha, som endast körs i big-endian-läge på Cray T3E).

Notera att termen bi-endian i första hand avser hur en processor behandlar dataåtkomst. Instruktionsåtkomst (hämtning av instruktionsord) på en viss processor kan fortfarande anta en fast endianness, även om dataåtkomst är helt bi-endian, även om detta inte alltid är fallet, t.ex. på Intels IA-64-baserade Itanium-CPU, som tillåter både och.

Bemärk också att vissa nominellt bi-endian-CPU:er kräver hjälp från moderkortet för att fullt ut byta endianness. De 32-bitars skrivbordsorienterade PowerPC-processorerna i little-endian-läge fungerar till exempel som little-endian ur de exekverande programmens synvinkel, men de kräver att moderkortet utför en 64-bitars swap över alla 8 byte lanes för att se till att den little-endian-synvinkeln kommer att gälla för I/O-enheter. I avsaknad av denna ovanliga moderkortshårdvara måste programvaran för enhetsdrivare skriva till olika adresser för att ångra den ofullständiga omvandlingen och måste också utföra ett normalt bytebyte.

Vissa CPU:er, t.ex. många PowerPC-processorer avsedda för inbäddad användning och nästan alla SPARC-processorer, tillåter val av endianness per sida.

SPARC-processorer sedan slutet av 1990-talet (SPARC v9-kompatibla processorer) gör det möjligt att välja dataindianitet med varje enskild instruktion som laddar från eller lagrar till minnet.

ARM-arkitekturen stöder två big-endian-lägen, som kallas BE-8 och BE-32. Processorer upp till ARMv5 stöder endast BE-32 eller ordinvariant läge. Här fungerar all naturligt justerad 32-bitars åtkomst som i little-endian-läget, men åtkomst till en byte eller ett 16-bitars ord omdirigeras till motsvarande adress och ojusterad åtkomst är inte tillåten. ARMv6 introducerar BE-8 eller byte-invariant läge, där åtkomst till en enda byte fungerar som i little-endian-läge, men åtkomst till ett 16-bitars, 32-bitars eller (från och med ARMv8) 64-bitars ord resulterar i en byte-swap av data. Detta förenklar åtkomst till ojusterade minnen samt minnesmappad åtkomst till andra register än 32-bitar.

Många processorer har instruktioner för att omvandla ett ord i ett register till motsatt endianness, det vill säga de byter ordningsföljden på bytena i ett 16-, 32- eller 64-bitarigt ord. Alla enskilda bitar är dock inte omvända.

Nyare CPU:er med Intel x86- och x86-64-arkitektur har en MOVBE-instruktion (Intel Core sedan generation 4, efter Atom), som hämtar ett ord i big-endian-format från minnet eller skriver ett ord till minnet i big-endian-format. Dessa processorer är annars helt och hållet little-endian. De hade också redan en rad swap-instruktioner för att vända byteordningen på innehållet i register, t.ex. när ord redan har hämtats från minnesplatser där de var i ”fel” endianness.

Floating pointEdit

Och även om dagens allestädes närvarande x86-processorer använder little-endian-lagring för alla typer av data (heltal, floating point) finns det ett antal hårdvaruarkitekturer där floating point-tal representeras i big-endian-form medan heltal representeras i little-endian-form. Det finns ARM-processorer som har halvt little-endian, halvt big-endian representation av flyttal för dubbelprecisionstal: båda 32-bitarsorden lagras i little-endian som heltalsregister, men det mest signifikanta först. Eftersom det har funnits många format för flyttal utan någon ”nätverks”-standardrepresentation för dem, använder XDR-standarden big-endian IEEE 754 som representation. Det kan därför tyckas märkligt att den utbredda IEEE 754-standarden för flyttal inte anger endianness. Teoretiskt sett innebär detta att även standard IEEE floating point-data som skrivs av en maskin kanske inte kan läsas av en annan maskin. På moderna standarddatorer (dvs. som tillämpar IEEE 754) kan man dock i praktiken anta att endianness är densamma för flyttal som för heltal, vilket gör konverteringen okomplicerad oavsett datatyp. (Små inbäddade system som använder speciella format för flyttal kan dock vara en annan sak.)

Data med varierande längdRedigera

De flesta instruktioner som hittills beaktats innehåller storleken (längden) på sina operander i operationskoden. Ofta är operandernas längd 1, 2, 4, 8 eller 16 byte, men det finns också arkitekturer där operandernas längd kan hållas i ett separat fält i instruktionen eller tillsammans med själva operanderna, t.ex. med hjälp av ett ordmärke. Ett sådant tillvägagångssätt tillåter operandlängder på upp till 256 byte eller till och med hela minnesstorleken.Datatyperna för sådana operander är teckensträngar eller BCD.

Maskiner som kan manipulera sådana data med en instruktion (t.ex. jämföra, addera) är t.ex. IBM 1401, 1410, 1620, System/3×0, ESA/390 och z/Architecture, alla av typen big-endian.

OptimizationEdit

Det little-endian-systemet har den egenskapen att samma värde kan läsas från minnet i olika längder utan att använda olika adresser (även när begränsningar för justering införs). Till exempel kan en 32-bitars minnesplats med innehållet 4A 00 00 00 00 läsas på samma adress som antingen 8-bitars (värde = 4A), 16-bitars (004A), 24-bitars (00004A) eller 32-bitars (0000004A), som alla behåller samma numeriska värde. Även om denna little-endian-egenskap sällan används direkt av högnivåprogrammerare, används den ofta av kodoptimerare samt av programmerare av assembler.

Enklare uttryckt motsvarar sådana optimeringar att följande C-kod returnerar true på de flesta little-endian-system:

union { uint8_t u8; uint16_t u16; uint32_t u32; uint64_t u64;} u = { .u64 = 0x4A };puts(u.u8 == u.u16 && u.u8 == u.u32 && u.u8 == u.u64 ? "true" : "false");

Som inte tillåts av C++ tillåts en sådan typbestämd kod som ”implementationsdefinierad” av C11-standarden och används vanligen i kod som interagerar med hårdvara.

Å andra sidan kan det i vissa situationer vara användbart att få en approximation av ett värde med flera byte eller ord genom att läsa endast den mest signifikanta delen i stället för den fullständiga representationen; en big-endian-processor kan läsa en sådan approximation genom att använda samma basadress som skulle användas för det fullständiga värdet.

Optimeringar av detta slag är inte överförbara mellan system med olika endianness.

BeräkningsordningRedigera

Vissa operationer i positionella talsystem har en naturlig eller föredragen ordning i vilken de elementära stegen ska utföras.Denna ordning kan påverka deras prestanda på småskaliga byte-adresserbara processorer och mikrokontroller.

Hur som helst hämtar högpresterande processorer vanligtvis typiska operander med flera byte från minnet på samma tid som de skulle ha hämtat en enskild byte, så maskinvarans komplexitet påverkas inte av byteordningen.

Operationer som börjar vid den minst signifikanta siffranRedigera

Addition, subtraktion och multiplikation börjar vid den minst signifikanta siffran och överför överföringen till den efterföljande mer signifikanta positionen.Att adressera data med flera siffror vid dess första byte (= minsta adress) är det dominerande adresseringsschemat.När denna första byte innehåller den minst signifikanta siffran – vilket motsvarar little-endianness, är genomförandet av dessa operationer marginellt enklare.

Operationer som börjar vid den mest signifikanta siffranRedigera

Sammanvägning och division börjar vid den mest signifikanta siffran och förflyttar en eventuell carry till de efterföljande mindre signifikanta siffrorna. För numeriska värden med fast längd (vanligtvis med längden 1,2,4,8,16) är genomförandet av dessa operationer marginellt enklare på big-endian-maskiner.

Operander med varierande längdRedigera

Många big-endian-processorer innehåller maskinvaruinstruktioner för lexikografisk jämförelse av teckensträngar med varierande längd (t.ex. IBM System/360 och dess efterföljare).

Operationer utan påverkanRedigera

Den normala datatransporten genom en tilldelningsangivelse är i princip oberoende av processorns endianitet.

Middle-endianRedigera

Numera andra ordningar, som generiskt kallas middle-endian eller mixed-endian, är möjliga. Ett sådant exempel utanför datavetenskapen är den vanliga amerikanska datumformateringen månad/dag/år.

PDP-endianEdit

PDP-11 är i princip ett 16-bitars little-endian-system. Instruktionerna för att konvertera mellan flyttal- och heltalsvärden i den valfria flyttalprocessorn i PDP-11/45, PDP-11/70 och i vissa senare processorer lagrade 32-bitars ”double precision integer long”-värden med de 16-bitars halvorna utbytta från den förväntade little-endian-ordningen. UNIX C-kompilatorn använde samma format för 32-bitars långa heltal. Denna ordning är känd som PDP-endian.

Ett sätt att tolka denna endianitet är att den lagrar ett 32-bitars heltal som två 16-bitars ord i big-endian, men orden i sig är little-endian (E.g. ”jag cog sin” skulle bli ”gaj goc nis”):

Lagring av ett 32-bitars heltal, 0x0A0B0C0D, på en PDP-11
ökande adresser →
0Bh 0Ah 0Dh 0Ch
0A0Bh 0C0Dh

De 16-bitarsvärden som anges här avser deras numeriska värden, inte deras faktiska layout.

Honeywell Series 16Edit

Honeywell Series 16 16-bitars datorer, inklusive Honeywell 316, är motsatsen till PDP-11 när det gäller att lagra 32-bitars ord i C. Den lagrar varje 16-bitars ord i big-endian ordning, men sammanfogar dem på little-endian sätt:

Lagring av ett 32-bitars heltal, 0x0A0B0C0D, på en Honeywell 316
ökande adresser →
0Ch 0Dh 0Ah 0Bh
…. 0C0Dh 0A0Bh

Intel IA-32 segmentdeskriptorerRedigera

Segmentdeskriptorer för IA-32 och kompatibla processorer behåller en 32-bitars basadress för segmentet som är lagrad i little-endian-ordning, men i fyra icke-konsekventiella bytes, på de relativa positionerna 2, 3, 4 och 7 i deskriptorns start.