Endianness

HistoryEdit

Molti processori storici ed esistenti usano una rappresentazione di memoria big-endian, esclusivamente o come opzione di progettazione. La rappresentazione di memoria big-endian è comunemente indicata come ordine di rete, come usato nella suite del protocollo Internet. Altri tipi di processori usano la rappresentazione di memoria little-endian; altri ancora usano un altro schema chiamato “middle-endian”, “mixed-endian” o “PDP-11-endian”.

Il System/360 IBM usa l’ordine byte big-endian, come i suoi successori System/370, ESA/390, e z/Architecture. Anche il PDP-10 usa l’indirizzamento big-endian per le istruzioni orientate al byte. Anche il minicomputer IBM Series/1 usa l’ordine di byte big-endian.

Gestire i dati di diversa endianness è talvolta chiamato il problema NUXI. Questa terminologia allude ai conflitti di ordine dei byte incontrati durante l’adattamento di UNIX, che girava sul PDP-11 mixed-endian, a un computer IBM Series/1 big-endian. Unix fu uno dei primi sistemi a permettere la compilazione dello stesso codice per piattaforme con diverse rappresentazioni interne. Uno dei primi programmi convertiti doveva stampare Unix, ma sulla Series/1 stampava invece nUxi.

Il Datapoint 2200 usa una semplice logica bit-seriale con little-endian per facilitare la propagazione dei carry. Quando Intel sviluppò il microprocessore 8008 per Datapoint, usò little-endian per compatibilità. Tuttavia, poiché Intel non fu in grado di consegnare l’8008 in tempo, Datapoint usò un equivalente di integrazione su media scala, ma il little-endian fu mantenuto nella maggior parte dei progetti Intel, incluso l’MCS-48 e l’8086 e i suoi successori x86. Il DEC Alpha, Atmel AVR, VAX, la famiglia MOS Technology 6502 (inclusi Western Design Center 65802 e 65C816), lo Zilog Z80 (inclusi Z180 e eZ80), l’Altera Nios II, e molti altri processori e famiglie di processori sono anche little-endian.

I processori Motorola 6800 / 6801, il 6809 e la serie 68000 usavano il formato big-endian.

L’Intel 8051, contrariamente ad altri processori Intel, si aspetta indirizzi a 16 bit per LJMP e LCALL in formato big-endian; tuttavia, le istruzioni xCALL memorizzano l’indirizzo di ritorno sullo stack in formato little-endian.

SPARC storicamente ha usato big-endian fino alla versione 9, che è bi-endian; analogamente i primi processori IBM POWER erano big-endian, ma i discendenti PowerPC e Power ISA sono ora bi-endian. L’architettura ARM era little-endian prima della versione 3, quando è diventata bi-endian.

Architetture attualiModifica

Le serie di processori Intel x86 e AMD64 / x86-64 usano il formato little-endian. Altre architetture di set di istruzioni che seguono questa convenzione, permettendo solo la modalità little-endian, includono Nios II, Andes Technology NDS32, e Qualcomm Hexagon.

Alcune architetture di set di istruzioni permettono l’esecuzione di software di entrambi gli endianness su un’architettura bi-endian. Questo include ARM AArch64, C-Sky, Power ISA, e RISC-V.

Le architetture esclusivamente big-endian includono l’IBM z/Architecture, Freescale ColdFire (che è basata sulla serie Motorola 68000), Atmel AVR32, e OpenRISC. I sistemi operativi IBM AIX e Oracle Solaris su Power ISA e SPARC bi-endian girano in modalità big-endian; alcune distribuzioni di Linux su Power sono passate alla modalità little-endian.

Bi-endiannessEdit

Alcune architetture (incluse ARM versioni 3 e superiori, PowerPC, Alpha, SPARC V9, MIPS, PA-RISC, SuperH SH-4 e IA-64) hanno un’impostazione che permette di commutare l’endianness nei data fetches e stores, instruction fetches, o entrambi. Questa caratteristica può migliorare le prestazioni o semplificare la logica dei dispositivi di rete e del software. La parola bi-endian, quando si parla di hardware, denota la capacità della macchina di calcolare o passare dati in entrambi i formati endian.

Molte di queste architetture possono essere commutate via software su un formato endian specifico (di solito quando il computer si avvia); tuttavia, su alcuni sistemi l’endianness di default è selezionato dall’hardware sulla scheda madre e non può essere cambiato via software (es.Ad esempio l’Alpha, che funziona solo in modalità big-endian sul Cray T3E).

Nota che il termine bi-endian si riferisce principalmente a come un processore tratta gli accessi ai dati. Gli accessi all’istruzione (fetches di instruction words) su un dato processore possono ancora assumere un endianness fisso, anche se gli accessi ai dati sono completamente bi-endian, sebbene questo non sia sempre il caso, come nella CPU Itanium di Intel basata su IA-64, che permette entrambi.

Nota anche che alcune CPU nominalmente bi-endian richiedono l’aiuto della scheda madre per cambiare completamente endianness. Per esempio, i processori PowerPC a 32-bit orientati al desktop in modalità little-endian si comportano come little-endian dal punto di vista dei programmi in esecuzione, ma richiedono che la scheda madre esegua uno swap a 64-bit su tutte le 8 corsie di byte per assicurare che la visione little-endian delle cose sia applicata ai dispositivi I/O. In assenza di questo insolito hardware della scheda madre, il software del driver del dispositivo deve scrivere a indirizzi diversi per annullare la trasformazione incompleta e deve anche eseguire un normale scambio di byte.

Alcune CPU, come molti processori PowerPC destinati all’uso embedded e quasi tutti i processori SPARC, permettono la scelta per pagina dell’endianness.

I processori SPARC dalla fine degli anni ’90 (processori conformi a SPARC v9) permettono di scegliere l’endianness dei dati con ogni singola istruzione che carica o memorizza in memoria.

L’architettura ARM supporta due modalità big-endian, chiamate BE-8 e BE-32. Le CPU fino ad ARMv5 supportano solo la modalità BE-32 o word-invariant. Qui ogni accesso naturalmente allineato a 32 bit funziona come nella modalità little-endian, ma l’accesso a un byte o a una parola di 16 bit viene reindirizzato all’indirizzo corrispondente e l’accesso non allineato non è consentito. ARMv6 introduce la modalità BE-8 o byte-invariante, dove l’accesso a un singolo byte funziona come in modalità little-endian, ma l’accesso a una parola a 16-bit, 32-bit o (a partire da ARMv8) 64-bit risulta in uno scambio di byte dei dati. Questo semplifica l’accesso alla memoria non allineata così come l’accesso mappato alla memoria a registri diversi da 32 bit.

Molti processori hanno istruzioni per convertire una parola in un registro nell’endianness opposto, cioè, scambiano l’ordine dei byte in una parola a 16, 32 o 64 bit. Tutti i singoli bit non sono però invertiti.

Le recenti CPU con architettura Intel x86 e x86-64 hanno un’istruzione MOVBE (Intel Core dalla generazione 4, dopo Atom), che recupera una parola in formato big-endian dalla memoria o scrive una parola in memoria in formato big-endian. Questi processori sono altrimenti completamente little-endian. Avevano anche già una serie di istruzioni di swap per invertire l’ordine dei byte del contenuto dei registri, come quando le parole sono già state recuperate da posizioni di memoria dove erano nell’endianness “sbagliato”.

Punto fluttuanteModifica

Anche se gli onnipresenti processori x86 di oggi usano la memorizzazione little-endian per tutti i tipi di dati (interi, in virgola mobile), ci sono un certo numero di architetture hardware in cui i numeri in virgola mobile sono rappresentati in forma big-endian mentre gli interi in forma little-endian. Ci sono processori ARM che hanno una rappresentazione in virgola mobile metà little-endian e metà big-endian per i numeri a doppia precisione: entrambe le parole a 32 bit sono memorizzate in little-endian come i registri interi, ma la più significativa per prima. Poiché ci sono stati molti formati in virgola mobile senza una rappresentazione standard “di rete” per loro, lo standard XDR usa l’IEEE 754 big-endian come rappresentazione. Può quindi sembrare strano che il diffuso standard in virgola mobile IEEE 754 non specifichi l’endianness. Teoricamente, questo significa che anche i dati in virgola mobile IEEE standard scritti da una macchina potrebbero non essere leggibili da un’altra. Tuttavia, sui moderni computer standard (cioè che implementano lo standard IEEE 754), si può in pratica assumere con sicurezza che l’endianness sia lo stesso per i numeri in virgola mobile come per gli interi, rendendo la conversione semplice indipendentemente dal tipo di dati. (I piccoli sistemi embedded che usano formati speciali in virgola mobile possono essere comunque un’altra questione.)

Dati di lunghezza variabileModifica

La maggior parte delle istruzioni considerate finora contengono la dimensione (lunghezza) dei suoi operandi all’interno del codice dell’operazione. Le lunghezze degli operandi spesso disponibili sono 1, 2, 4, 8 o 16 byte, ma ci sono anche architetture in cui la lunghezza di un operando può essere tenuta in un campo separato dell’istruzione o con l’operando stesso, per esempio per mezzo di un segno di parola. Un tale approccio permette lunghezze dell’operando fino a 256 byte o persino l’intera dimensione della memoria.I tipi di dati di tali operandi sono stringhe di caratteri o BCD.

Le macchine in grado di manipolare tali dati con un’istruzione (ad esempio confrontare, aggiungere) sono ad esempio IBM 1401, 1410, 1620, System/3×0, ESA/390, e z/Architecture, tutti di tipo big-endian.

OptimizationEdit

Il sistema little-endian ha la proprietà che lo stesso valore può essere letto dalla memoria a lunghezze diverse senza usare indirizzi diversi (anche quando sono imposte restrizioni di allineamento). Per esempio, una locazione di memoria di 32 bit con contenuto 4A 00 00 00 può essere letta allo stesso indirizzo come 8 bit (valore = 4A), 16 bit (004A), 24 bit (00004A), o 32 bit (0000004A), tutti mantenendo lo stesso valore numerico. Sebbene questa proprietà little-endian sia raramente usata direttamente dai programmatori di alto livello, è spesso impiegata dagli ottimizzatori di codice così come dai programmatori di linguaggio assembly.

In termini più concreti, tali ottimizzazioni sono l’equivalente del seguente codice C che restituisce true sulla maggior parte dei sistemi little-endian:

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

Sebbene non sia permesso dal C++, tale codice type punning è permesso come “implement-defined” dallo standard C11 e comunemente usato nel codice che interagisce con l’hardware.

D’altra parte, in alcune situazioni può essere utile ottenere un’approssimazione di un valore multi-byte o multi-parola leggendo solo la sua porzione più significativa invece della rappresentazione completa; un processore big-endian può leggere tale approssimazione usando lo stesso indirizzo base che sarebbe usato per il valore completo.

Ottimizzazioni di questo tipo non sono portabili attraverso sistemi di diversa endianness.

Ordine di calcoloModifica

Alcune operazioni nei sistemi di numeri posizionali hanno un ordine naturale o preferito in cui i passi elementari devono essere eseguiti.Questo ordine può influenzare le loro prestazioni su processori e microcontrollori indirizzabili a byte su piccola scala.

Tuttavia, i processori ad alte prestazioni di solito recuperano operandi tipici a più byte dalla memoria nello stesso tempo in cui avrebbero recuperato un singolo byte, quindi la complessità dell’hardware non è influenzata dall’ordine dei byte.

Le operazioni che iniziano dalla cifra meno significativaModifica

Addizione, sottrazione e moltiplicazione iniziano dalla posizione della cifra meno significativa e propagano il riporto alla successiva posizione più significativa.Indirizzare i dati a più cifre al suo primo (= indirizzo più piccolo) byte è lo schema di indirizzamento predominante.Quando questo primo byte contiene la cifra meno significativa – il che equivale a una piccola-endianità, allora l’implementazione di queste operazioni è marginalmente più semplice.

Operazioni che iniziano dalla cifra più significativaModifica

Confronto e divisione iniziano dalla cifra più significativa e propagano un possibile riporto alle successive cifre meno significative. Per valori numerici di lunghezza fissa (tipicamente di lunghezza 1,2,4,8,16), l’implementazione di queste operazioni è marginalmente più semplice sulle macchine big-endian.

Operandi di lunghezza variabileModifica

Molti processori big-endian contengono istruzioni hardware per confrontare lessicograficamente stringhe di caratteri di lunghezza variabile (es. IBM System/360 e i suoi successori).

Operazioni senza impattoModifica

Il normale trasporto di dati da una dichiarazione di assegnazione è in linea di principio indipendente dall’endianness del processore.

Middle-endianEdit

Sono possibili numerosi altri ordinamenti, genericamente chiamati middle-endian o mixed-endian. Un esempio al di fuori dell’informatica è la formattazione standard della data americana di mese/giorno/anno.

PDP-endianEdit

Il PDP-11 è in principio un sistema little-endian a 16 bit. Le istruzioni per convertire tra valori in virgola mobile e interi nel processore opzionale in virgola mobile del PDP-11/45, PDP-11/70, e in alcuni processori successivi, memorizzavano valori a 32 bit “double precision integer long” con le metà a 16 bit scambiate dal previsto ordine little-endian. Il compilatore UNIX C usava lo stesso formato per gli interi lunghi a 32 bit. Questo ordinamento è noto come PDP-endian.

Un modo per interpretare questa endianness è che memorizza un intero a 32 bit come due parole a 16 bit in big-endian, ma le parole stesse sono little-endian (E.g. “jag cog sin” sarebbe “gaj goc nis”):

Salvataggio di un intero a 32 bit, 0x0A0B0C0D, su un PDP-11
indirizzo crescente →
0Bh 0Ah 0Dh 0Ch
0A0Bh 0C0Dh

I valori a 16 bit qui si riferiscono ai loro valori numerici, non alla loro effettiva disposizione.

Honeywell Series 16Edit

I computer Honeywell Series a 16 bit, incluso l’Honeywell 316, sono l’opposto del PDP-11 nel memorizzare parole a 32 bit in C. Memorizza ogni parola a 16 bit in ordine big-endian, ma le unisce in modo little-endian:

memorizzazione di un intero a 32 bit, 0x0A0B0C0D, su un Honeywell 316
indirizzi crescenti →
0Ch 0Dh 0Ah 0Bh
.. 0C0Dh 0A0Bh

Descrittori di segmento Intel IA-32Modifica

I descrittori di segmento di processori IA-32 e compatibili mantengono un indirizzo base di 32 bit del segmento memorizzato in ordine little-endian, ma in quattro byte non consecutivi, nelle posizioni relative 2, 3, 4 e 7 dell’inizio del descrittore.