Newsgroup: it.hobby.elettronica.digitale
Titolo: Big-endian VS Little-endian

Zalve a tutti,
Qualcuno sa se c'è un modo per determinare a tempo di compilazione se il 
compilatore ( e l'archidettura su cui sta compilando ) è Big-endian o 
Little-endian?
Più in generale, sappiamo che i gli x86 sono Little-endian ( 0x1234 
diventa 0x34 0x12 ).
I Pic cosa sono?
Gli Arm?
-- 
Il Razziatore,
"Lo sviluppo di una nazione si misura anche dallo stato della sua rete 
ferroviaria". Camillo Benso Conte di Cavour
"Per tutto quanto non previsto nel presente regolamento il capostazione 
deve usare senno e ponderatezza." Regolamento d'esercizio FS
-----------------------------------------------
MSN   : 
IlRazz...@netscape.net
ICQ   : 67552596
Yhaoo : Razziatore82
-----------------------------------------------
Founder of MediaPlayer Project
http://razziatore.no-ip.com/mpp/

 Gli Arm?
Possono essere sia big che little endian, lo decidi tu al boot.
-- 
emboliaschizoide.splinder.com

 
Avevo letto questa cosa, ma come si decide? Voglio dire c'è un opzione 
da qualche parte mentre si compila/si flasha?
O magari c'è qualche
#pragma


 Possono essere sia big che little endian, lo decidi tu al boot.
Non c'era un opcode a runtime?

 da qualche parte mentre si compila/si flasha?
A basso livello credo che dipenda da ogni processore; alcuni sono
preimpostati a una certa endianness e non la puoi cambiare, altri hanno dei
pin speciali che ti permettono di selezionarla ad esempio con dei jumper, e
altri te lo fanno fare anche a run time con determinate istruzioni. Un
esempio sono certe distribuzioni di Linux per ARM che supportano solo il
little endian, mentre il boot deve essere fatto in big endian per questioni
di architettura; in questo caso il kernel deve eseguire lo switch durante
il boot.
A livello di compilatore, vale quanto detto sopra. Il gcc ad esempio ha le
machine options -mlittle-endian e -mbig-endian.
-- 
emboliaschizoide.splinder.com

 altri te lo fanno fare anche a run time con determinate istruzioni.
La prima è la più brutta, l'ultima è più da smanettoni, la terza è la 
più comoda IMHO ( lo imposti una volta e tanti saluti ). Ma come mai ARM 
che è un CORE ben preciso ha tutte queste differenze?


   
Forse solo per i PIC :-)
Quasi tutti i micro a 8bit moderni che non siano controller supereconomici
supportano almeno un accesso a 16bit in memoria esterna o interna il che
comporta un accesso hardware BigEN o LittleEN, cioe' hanno o registri
interni a 16 bit o coppie contigue di registri a 8bit utilizzabili a 
16bit con 
organizzazione ben definita (tipo AVR, Zx, 803x etc.).
Comunque e' vero che in generale e' il compilatore che se ne occupa.

    x.d16=0x55AA;   //  se BigEN, in memoria 0x55, 0xAA, else 0xAA, 0x55...
Curiosa la scelta della word 0x55AA, l'hai scelta a caso o ha un motivo 
particolare?


 Comunque e' vero che in generale e' il compilatore che se ne occupa.
Beh, i PIC non sono certo rinomati per la loro architettura di accesso alla
memoria. :)
Si tratta più di una questione di semantica che altro. In un processore a
16 bit "propriamente detto" tutti gli opcodes o quasi supportano operazioni
a 16 bit, il che rende la scelta della endianness pressoché obbligata. In
un processore a 8 bit che magari ha un paio di istruzioni specifiche a 16
bit (tipicamente un MOV da memoria a accumulatore o viceversa) la scelta è
già meno ovvia. Soprattutto quando le suddette istruzioni hanno
comportamenti "strani", come avviene a volte; ad esempio se fai girare
questo codice su TMS320C54xx (DSP a 16 bit della Texas Instruments):
unsigned short a[4] = {0,0,0,0};
*(unsigned long*)(a+2) = 0x11112222;
// Ora a={0,0x2222,0x1111,0}.
unsigned short b[4] = {0,0,0,0};
*(unsigned long*)(b+1) = 0x11112222;
// Ora b={0,0x1111,0x2222,0}.
Il problema è che il compilatore gestisce l'accesso a 32 bit usando
l'apposito opcode del DSP, che però funziona diversamente con indirizzi
pari e dispari. A mio parere avrebbero fatto decisamente meglio a splittare
le operazioni a 32 bit (che tanto richiedono due cicli di clock comunque)
in due operazioni a 16 bit che si comportassero in maniera consistente. Ma
d'altra parte TI non è nuova a queste scelte progettuali apparentemente
strane, dovute probabilmente ad architetture legacy che oggigiorno nessuno
sa più nemmeno quali fossero. :)
-- 
emboliaschizoide.splinder.com

brix99luftballons ha scritto:

alternativa:
char isBigEndian(void)
{
int i = 1
char * p = (char *) &i;
return *p;	
}

 motivo particolare?
Motivi storici ;-)
0101.0101
1010.1010

 }
Buona, apettiamo anche qualche altra variante ...

 particolare?
Ne hai da mangiare ancora parecchia di pappina, bimbo. :-)

brix99luftballons ha scritto:

Avevo imaginato qualcosa del genere :) Anche se non lo avevo mai 
guardato "dentro" i byte. Io personalmente associavo il tutto alla firma 
che deve avere il primo settore di un disco perché questo sia ritenuto 
"bootable" :D si vede che sono un informatico eh? :D


 ritenuto "bootable" :D si vede che sono un informatico eh? :D
Non solo per il disco ;-)
A volte un pattern particolare viene chiamato magic number....
Nei PC è l' identificatore per la presenza dei vari ROM bios che possono
trovarsi nella zona storica di espansione periferiche (da 0xA0000 a 
0xE0000 in real mode).
Perche pensi sia stato scelto un marker come 0x55AA o 0xAA55 ?
Perche', data la conformazione di bit, si riteneva poco probabile che
una simile sequenza potesse apparire casualmente in memoria, vuoi
perche' non presente o perche' non inizializzata ;-)
Ciao
B.

 perche' non presente o perche' non inizializzata ;-)
Non credo fossero cosě ingenui da commettere un errore cosě banale.
A parte le configurazioni 0x00 e 0xff, piů probabili solo per le
caratteristiche dei trasceiver del bus, gli altri pattern sono tutti
equiprobabili.
Piuttosto un pattern del genere puň essere utile per scartare banchi in cui
due linee dati adiacenti siano in corto.

 
Zalve a te,
dunque, se parliamo di architetture a 32 bit, ho visto spesso qualcosa 
del tipo
#if BYTE_ORDER == BIG_ENDIAN
#define WE_ARE_BIGENDIANS
#elif BYTE_ORDER != LITTLE_ENDIAN
# error "cannot determine endianess"
#endif
...
#ifdef WE_ARE_BIGENDIANS
... codice big endian
#else
... codice little endian
#endif
Nella mia esperienza di crosscomilatori (gcc, IAR embedded workbench e 
embeded visualC++) ha sempre funzionato.
BYTE_ORDER, BIG_ENDIAN e LITTLE_ENDIAN di solito sono definiti negli 
#include delle librerie standard, a volte potrebbero essere predefiniti 
dal compilatore.
Tieni conto che a volte nella stesa architettura l'endianess dei 
floating point può essere diversa da quella degli interi (ARM con fpu), 
in quel caso bisogna vedere se è definito __IEEE_BIG_ENDIAN o 
__IEEE_LITTLE_ENDIAN.
Poi c'è una storica PDP endianess, che è "LSB first in word, MSW first 
in long", un mix insomma, ma quella è un'altra storia.
A volte comunque conviene decidere a runtime, e ad ogni modo le routine 
di test dell'endianess permettono di verificare che le direttive del 
preprocessore siano state interpretate nel modo giusto.

Cortex2core ha scritto:
[cut]
Molto molto interessante! Grazie!
