Endianness

HistoryEdit

Mange historiske og eksisterende processorer bruger en big-endian hukommelsesrepræsentation, enten udelukkende eller som en designmulighed. Big-endian-hukommelsesrepræsentation kaldes almindeligvis for netværksorden, som den anvendes i internetprotokolpakken. Andre processortyper anvender little-endian hukommelsesrepræsentation; andre anvender endnu et andet skema kaldet “middle-endian”, “mixed-endian” eller “PDP-11-endian”.

IBM System/360 anvender big-endian byteorden, ligesom efterfølgerne System/370, ESA/390 og z/Architecture. PDP-10 anvender også big-endian-adressering for byte-orienterede instruktioner. IBM Series/1-minicomputeren anvender også big-endian-byteorden.

Håndtering af data af forskellig endianness kaldes undertiden for NUXI-problemet. Denne terminologi hentyder til de byteordenskonflikter, der opstod under tilpasningen af UNIX, som kørte på den blandede-endian PDP-11, til en big-endian IBM Series/1-computer. Unix var et af de første systemer, der gjorde det muligt at kompilere den samme kode til platforme med forskellige interne repræsentationer. Et af de første programmer, der blev konverteret, skulle udskrive Unix, men på Series/1 udskrev det i stedet nUxi.

Datapoint 2200 anvender simpel bit-seriel logik med little-endian for at lette carry-propagation. Da Intel udviklede 8008-mikroprocessoren til Datapoint, brugte de little-endian af hensyn til kompatibiliteten. Da Intel imidlertid ikke var i stand til at levere 8008’eren i tide, anvendte Datapoint en tilsvarende integration i medium skala, men little-endianess blev bibeholdt i de fleste Intel-designs, herunder MCS-48 og 8086’eren og dens x86-efterfølgere. DEC Alpha, Atmel AVR, VAX, MOS Technology 6502-familien (herunder Western Design Center 65802 og 65C816), Zilog Z80 (herunder Z180 og eZ80), Altera Nios II og mange andre processorer og processorfamilier er også little-endian.

Motorolas 6800 / 6801, 6809- og 68000-processorserien brugte big-endian-formatet.

Intel 8051 forventer i modsætning til andre Intel-processorer 16-bit-adresser til LJMP og LCALL i big-endian-format; xCALL-instruktionerne gemmer dog returadressen på stakken i little-endian-format.

SPARC brugte historisk set big-endian indtil version 9, som er bi-endian; tilsvarende var tidlige IBM POWER-processorer big-endian, men PowerPC- og Power ISA-efterkommerne er nu bi-endian-format. ARM-arkitekturen var little-endian før version 3, hvor den blev bi-endian.

Nuværende arkitekturerRediger

Intel x86- og AMD64 / x86-64-serier af processorer anvender det little-endian-format. Andre instruktionssætarkitekturer, der følger denne konvention, og som kun tillader little-endian-tilstand, omfatter Nios II, Andes Technology NDS32 og Qualcomm Hexagon.

Somme instruktionssætarkitekturer tillader kørsel af software af begge endianness på en bi-endian-arkitektur. Dette omfatter ARM AArch64, C-Sky, Power ISA og RISC-V.

Solut big-endian-arkitekturer omfatter IBM z/Arkitekturen, Freescale ColdFire (som er Motorola 68000-serie-baseret), Atmel AVR32 og OpenRISC. IBM AIX- og Oracle Solaris-operativsystemerne på bi-endian Power ISA og SPARC kører i big-endian-tilstand; nogle distributioner af Linux på Power er overgået til little-endian-tilstand.

Bi-endiannessEdit

Nogle arkitekturer (herunder ARM version 3 og derover, PowerPC, Alpha, SPARC V9, MIPS, PA-RISC, SuperH SH-4 og IA-64) har en indstilling, der giver mulighed for omskiftelig endianness i data hentninger og lagringer, instruktionshentninger eller begge dele. Denne funktion kan forbedre ydeevnen eller forenkle logikken i netværksenheder og -software. Når ordet bi-endian omtaler hardware, betegner det maskinens evne til at beregne eller videregive data i begge endianformater.

Mange af disse arkitekturer kan via software skiftes til et bestemt endianformat som standard (hvilket normalt sker, når computeren startes op); på nogle systemer vælges standard endianessystemet imidlertid af hardware på bundkortet og kan ikke ændres via software (f.eks.f.eks. Alpha, som kun kører i big-endian-tilstand på Cray T3E).

Bemærk, at udtrykket bi-endian primært henviser til, hvordan en processor behandler datatilgange. Instruktionsadgange (hentninger af instruktionsord) på en given processor kan stadig antage en fast endianess, selv om dataadgange er fuldt ud bi-endian, selv om dette ikke altid er tilfældet, f.eks. på Intels IA-64-baserede Itanium CPU, som tillader begge dele.

Bemærk også, at nogle nominelt bi-endian CPU’er kræver hjælp fra bundkortet for fuldt ud at skifte endianess. F.eks. opfører de 32-bit desktop-orienterede PowerPC-processorer i little-endian-tilstand sig som little-endian set fra de udførende programmers synspunkt, men de kræver, at bundkortet udfører en 64-bit swap på tværs af alle 8 byte lanes for at sikre, at little-endian-synspunktet vil gælde for I/O-enheder. I mangel af denne usædvanlige hardware på bundkortet skal enhedsdriver-software skrive til forskellige adresser for at fortryde den ufuldstændige transformation og skal også udføre en normal byte-swap.

Nogle CPU’er, f.eks. mange PowerPC-processorer beregnet til indlejret brug og næsten alle SPARC-processorer, giver mulighed for valg af endianness pr. side.

SPARC-processorer siden slutningen af 1990’erne (SPARC v9-kompatible processorer) tillader, at data-endianess vælges med hver enkelt instruktion, der indlæses fra eller lagres til hukommelse.

ARM-arkitekturen understøtter to big-endian-tilstande, kaldet BE-8 og BE-32. CPU’er op til ARMv5 understøtter kun BE-32 eller ordinvariant tilstand. Her fungerer enhver naturligt justeret 32-bits adgang som i little-endian-tilstand, men adgang til en byte eller et 16-bits ord omdirigeres til den tilsvarende adresse, og ujusteret adgang er ikke tilladt. ARMv6 introducerer BE-8 eller byte-invariant tilstand, hvor adgang til en enkelt byte fungerer som i little-endian-tilstand, men adgang til et 16-bit, 32-bit eller (fra ARMv8) 64-bit ord resulterer i en byte-swap af dataene. Dette forenkler ualigneret hukommelsesadgang samt hukommelsestilknytning til andre registre end 32 bit.

Mange processorer har instruktioner til at konvertere et ord i et register til den modsatte endianitet, dvs. at de bytter rækkefølgen af bytes i et 16-, 32- eller 64-bit ord. Alle de enkelte bits omvendes dog ikke.

Nyere CPU’er med Intel x86- og x86-64-arkitektur har en MOVBE-instruktion (Intel Core siden generation 4, efter Atom), som henter et ord i big-endian-format fra hukommelsen eller skriver et ord til hukommelsen i big-endian-format. Disse processorer er ellers helt igennem little-endian-format. De havde også allerede en række swap-instruktioner til at vende byte-rækkefølgen af indholdet af registre, f.eks. når ord allerede er blevet hentet fra hukommelsesplaceringer, hvor de var i det “forkerte” endianness.

Floating pointEdit

Selv om de allestedsnærværende x86-processorer i dag anvender little-endian-lagring til alle typer data (heltal, floating point), findes der en række hardwarearkitekturer, hvor floating point-tallene er repræsenteret i big-endian-form, mens heltal er repræsenteret i little-endian-form. Der findes ARM-processorer, der har halvt little-endian, halvt big-endian floating-point-repræsentation for dobbeltpræcisionstal: begge 32-bit ord lagres i little-endian ligesom heltalsregistre, men det mest signifikante først. Da der har været mange floating-point-formater uden nogen “netværks”-standardrepræsentation for dem, bruger XDR-standarden big-endian IEEE 754 som sin repræsentation. Det kan derfor forekomme mærkeligt, at den udbredte IEEE 754-flydepunktsstandard ikke angiver endianessystemet. Teoretisk set betyder det, at selv standard IEEE-flydepunktsdata, der er skrevet af en maskine, måske ikke kan læses af en anden maskine. På moderne standardcomputere (dvs. som implementerer IEEE 754) kan man dog i praksis roligt antage, at endianness er den samme for floating-point-tal som for hele tal, hvilket gør konverteringen ukompliceret uanset datatype. (Små indlejrede systemer, der anvender specielle floating-point-formater, kan dog være en anden sag.)

Data med variabel længdeRediger

De fleste instruktioner, der hidtil har været behandlet, indeholder størrelsen (længderne) af deres operander i operationskoden. Ofte er de tilgængelige operandlængder 1, 2, 4, 8 eller 16 bytes, men der findes også arkitekturer, hvor operandens længde kan holdes i et separat felt i instruktionen eller sammen med selve operanden, f.eks. ved hjælp af et ordmærke. En sådan fremgangsmåde tillader operandlængder på op til 256 bytes eller endog fuld hukommelsesstørrelse.Datatyperne for sådanne operander er tegnstrenge eller BCD.

Maskiner, der er i stand til at manipulere sådanne data med én instruktion (f.eks. sammenligne, tilføje), er f.eks. IBM 1401, 1410, 1620, System/3×0, ESA/390 og z/Arkitekturen, alle af typen big-endian.

OptimeringRedigering

Det little-endian-system har den egenskab, at den samme værdi kan læses fra hukommelsen i forskellige længder uden brug af forskellige adresser (selv når der er pålagt justeringsrestriktioner). F.eks. kan en 32-bit hukommelsesplacering med indhold 4A 00 00 00 00 00 læses på samme adresse som enten 8-bit (værdi = 4A), 16-bit (004A), 24-bit (00004A) eller 32-bit (0000004A), som alle bevarer den samme numeriske værdi. Selv om denne little-endian-egenskab sjældent bruges direkte af programmører på højt niveau, anvendes den ofte af kodeoptimeringer samt af programmører af assembler-sprog.

Mere konkret svarer sådanne optimeringer til, at følgende C-kode returnerer true på de fleste little-endian-systemer:

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");

Selv om den ikke er tilladt i C++, er en sådan typepunningskode tilladt som “implementeringsdefineret” af C11-standarden og anvendes almindeligvis i kode, der interagerer med hardware.

På den anden side kan det i nogle situationer være nyttigt at opnå en tilnærmelse af en multibyte- eller multiordværdi ved kun at læse den mest betydningsfulde del i stedet for den komplette repræsentation; en big-endian-processor kan læse en sådan tilnærmelse ved hjælp af den samme base-adresse, som ville blive brugt til den fulde værdi.

Optimeringer af denne art er ikke overførbare på tværs af systemer med forskellig endianness.

BeregningsrækkefølgeRediger

Nogle operationer i positionelle talsystemer har en naturlig eller foretrukken rækkefølge, i hvilken de elementære trin skal udføres.Denne rækkefølge kan påvirke deres ydeevne på små processorer og mikrocontrollere med byteadresserbare processorer og mikrocontrollere.

Men højtydende processorer henter normalt typiske multibyte-operander fra hukommelsen på samme tid, som de ville have hentet en enkelt byte, så hardwarens kompleksitet påvirkes ikke af byte-rækkefølgen.

Operationer, der starter ved det mindst betydningsfulde cifferRediger

Addition, subtraktion og multiplikation starter ved den mindst betydningsfulde cifferposition og propagere overførslen til den efterfølgende mere betydningsfulde position.Adressering af data med flere cifre ved den første (= mindste adresse) byte er det fremherskende adresseringsskema.Når denne første byte indeholder det mindst betydende ciffer – hvilket svarer til little-endianness, er implementeringen af disse operationer marginalt enklere.

Operationer, der starter ved det mest betydende cifferRediger

Sammenligning og division starter ved det mest betydende ciffer og forplanter en eventuel carry til de efterfølgende mindre betydende cifre. For numeriske værdier af fast længde (typisk af længde 1,2,4,8,16) er implementeringen af disse operationer marginalt enklere på big-endian-maskiner.

Operander af varierende længdeRediger

Mange big-endian-processorer indeholder hardwareinstruktioner til leksikografisk sammenligning af tegnstrenge af varierende længde (f.eks. IBM System/360 og dens efterfølgere).

Operationer uden påvirkningRediger

Den normale datatransport ved en tildelingsanvisning er i princippet uafhængig af processorens endianitet.

Middle-endianRediger

Numre andre ordneringer, der generisk kaldes middle-endian eller mixed-endian, er mulige. Et sådant eksempel uden for datalogien er den amerikanske standarddatformatering med måned/dag/år.

PDP-endianEdit

PDP-11 er i princippet et 16-bit little-endian-system. Instruktionerne til at konvertere mellem floating-point- og heltalsværdier i den valgfrie floating-point-processor i PDP-11/45, PDP-11/70 og i nogle senere processorer lagrede 32-bit “double precision integer long”-værdier med de 16-bit halvdele byttet om i forhold til den forventede little-endian-orden. UNIX C-compileren brugte det samme format til 32-bit lange hele tal. Denne rækkefølge er kendt som PDP-endian.

En måde at fortolke denne endianitet på er, at den gemmer et 32-bit heltal som to 16-bit ord i big-endian, men at ordene selv er little-endian (E.g. “jag cog sin” ville være “gaj goc nis”):

Lagring af et 32-bit heltal, 0x0A0B0B0C0D, på en PDP-11
stigende adresser →
0Bh 0Ah 0Dh 0Ch
0A0Bh 0C0Dh

De 16-bit værdier her henviser til deres numeriske værdier, ikke til deres faktiske layout.

Honeywell Series 16Rediger

De 16-bits 16-bit computere i Honeywell Series 16, herunder Honeywell 316, er det modsatte af PDP-11, når det gælder lagring af 32-bit ord i C. Den lagrer hvert 16-bit ord i big-endian rækkefølge, men sammenføjer dem på little-endian måde:

Lagring af et 32-bit heltal, 0x0A0B0C0D, på en Honeywell 316
stigende adresser →
0Ch 0Dh 0Ah 0Bh
…. 0C0Dh 0A0Bh

Intel IA-32 segmentdeskriptorerRediger

Segmentdeskriptorer i IA-32 og kompatible processorer beholder en 32-bit basisadresse for segmentet gemt i little-endian-orden, men i fire ikke-sammenhængende bytes, på de relative positioner 2, 3, 4 og 7 af deskriptorens start.