Differenze tra le versioni di "Conversione Big-Endian/Little-Endian"
Riga 18: | Riga 18: | ||
− | + | =Conversione ''Big-Endian''/''Little-Endian'' e viceversa di un valore a 16bit= | |
La formula astratta per ottenere la conversione ''Big-Endian''/''Little-Endian'' e viceversa di un valore a 16bit (= 2 byte, ossia di tipo ''Short'') può essere la seguente (anche se [http://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c le modalità sono molteplici] per ottenere la conversione): | La formula astratta per ottenere la conversione ''Big-Endian''/''Little-Endian'' e viceversa di un valore a 16bit (= 2 byte, ossia di tipo ''Short'') può essere la seguente (anche se [http://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c le modalità sono molteplici] per ottenere la conversione): | ||
((valore >> 8) & 0x00FF) | ((valore << 8) & 0xFF00) | ((valore >> 8) & 0x00FF) | ((valore << 8) & 0xFF00) | ||
Riga 26: | Riga 26: | ||
* Uso dell'operatore ''OR'' combinato con operazione di scorrimento dei bit a sinistra. | * Uso dell'operatore ''OR'' combinato con operazione di scorrimento dei bit a sinistra. | ||
− | + | ==Uso delle funzioni di scorrimento dei bit a destra ed a sinistra== | |
− | |||
Questa modalità è in sintassi così espressa: | Questa modalità è in sintassi così espressa: | ||
Hex((Shr(&''valore'', 8) And &FF) Or (Shl(&''valore'', 8) And &FF00&), 4) As String | Hex((Shr(&''valore'', 8) And &FF) Or (Shl(&''valore'', 8) And &FF00&), 4) As String | ||
Riga 34: | Riga 33: | ||
<BR>V'è da sottolineare che il il valore ''&FF00&'' necessita assolutamente alla fine del carattere '''&''', poiché, se non lo si ponesse, avremmo come risultato un valore in esadecimale di 3 byte ! <SUP>[ [[#Note|Nota 1]] ]</sup> | <BR>V'è da sottolineare che il il valore ''&FF00&'' necessita assolutamente alla fine del carattere '''&''', poiché, se non lo si ponesse, avremmo come risultato un valore in esadecimale di 3 byte ! <SUP>[ [[#Note|Nota 1]] ]</sup> | ||
− | + | ==Uso di esplicite operazioni matematiche== | |
− | |||
Se si vorranno utilizzare esplicite operazioni matematiche anziché funzioni Gambas, si potrà adoperare la seguente formula: | Se si vorranno utilizzare esplicite operazioni matematiche anziché funzioni Gambas, si potrà adoperare la seguente formula: | ||
Hex(((&''valore'' \ CInt(2 ^ 8)) And &FF) Or ((&''valore'' * CInt(2 ^ 8)) And &FF00&), 4) As String | Hex(((&''valore'' \ CInt(2 ^ 8)) And &FF) Or ((&''valore'' * CInt(2 ^ 8)) And &FF00&), 4) As String | ||
Riga 41: | Riga 39: | ||
Hex(((&''valore'' \ CInt(2 ^ 8)) And &FF) Or CShort(((&''valore'' * CInt(2 ^ 8)) And &FF00)), 4) As String | Hex(((&''valore'' \ CInt(2 ^ 8)) And &FF) Or CShort(((&''valore'' * CInt(2 ^ 8)) And &FF00)), 4) As String | ||
− | + | ==Uso dell'operatore ''OR'' con operazione di scorrimento dei bit a sinistra== | |
− | |||
Mostriamo un esempio pratico con l'operatore ''OR'' combinato con operazione di scorrimento dei bit a sinistra, in cui convertiremo il valore esadecimale ''0x2301'' di tipo ''Short'' da ''Little-Endian'' a ''Big-Endian'': | Mostriamo un esempio pratico con l'operatore ''OR'' combinato con operazione di scorrimento dei bit a sinistra, in cui convertiremo il valore esadecimale ''0x2301'' di tipo ''Short'' da ''Little-Endian'' a ''Big-Endian'': | ||
'''Public''' Sub Main() | '''Public''' Sub Main() | ||
Riga 63: | Riga 60: | ||
− | + | =Conversione ''Big-Endian''/''Little-Endian'' e viceversa di un valore a 32bit= | |
La formula astratta per ottenere la conversione ''Big-Endian''/''Little-Endian'' di un valore a 32bit (= 4 byte, ossia di tipo ''Integer'') può essere la seguente: | La formula astratta per ottenere la conversione ''Big-Endian''/''Little-Endian'' di un valore a 32bit (= 4 byte, ossia di tipo ''Integer'') può essere la seguente: | ||
((valore >> 24) & 0xff) | ((valore << 8) & 0xff0000) | ((valore >> 8) & 0xff00) | ((valore << 24) & 0xff000000) | ((valore >> 24) & 0xff) | ((valore << 8) & 0xff0000) | ((valore >> 8) & 0xff00) | ((valore << 24) & 0xff000000) | ||
Riga 71: | Riga 68: | ||
* Uso dell'operatore ''OR'' combinato con operazione di scorrimento dei bit a sinistra. | * Uso dell'operatore ''OR'' combinato con operazione di scorrimento dei bit a sinistra. | ||
− | + | ==Uso delle funzioni di scorrimento dei bit a destra ed a sinistra== | |
− | |||
Questa modalità è in sintassi così espressa: | Questa modalità è in sintassi così espressa: | ||
Hex((Shr(&''valore'', 24) And &FF) Or (Shl(&''valore'', 8) And &FF0000) Or (Shr(&''valore'', 8) And &FF00&) Or (Shl(&''valore'', 24) And &FF000000), 8) A String | Hex((Shr(&''valore'', 24) And &FF) Or (Shl(&''valore'', 8) And &FF0000) Or (Shr(&''valore'', 8) And &FF00&) Or (Shl(&''valore'', 24) And &FF000000), 8) A String | ||
− | + | ==Uso di esplicite operazioni matematiche== | |
− | |||
Se si vorranno utilizzare esplicite operazioni matematiche anziché funzioni Gambas, si potrà adoperare la seguente formula: | Se si vorranno utilizzare esplicite operazioni matematiche anziché funzioni Gambas, si potrà adoperare la seguente formula: | ||
Hex(((&''valore'' \ CInt(2 ^ 24)) And &FF) Or ((&''valore'' * CInt(2 ^ 8)) And &FF0000) Or ((&''valore'' \ CInt(2 ^ 8)) And &FF00&) Or ((&''valore'' * CInt(2 ^ 24)) And &FF000000), 8) | Hex(((&''valore'' \ CInt(2 ^ 24)) And &FF) Or ((&''valore'' * CInt(2 ^ 8)) And &FF0000) Or ((&''valore'' \ CInt(2 ^ 8)) And &FF00&) Or ((&''valore'' * CInt(2 ^ 24)) And &FF000000), 8) | ||
Riga 83: | Riga 78: | ||
Hex(((&''valore'' \ CInt(2 ^ 24)) And &FF) Or ((&''valore'' * CInt(2 ^ 8)) And &FF0000) Or CShort(((&''valore'' \ CInt(2 ^ 8)) And &FF00)) Or ((&''valore'' * CInt(2 ^ 24)) And &FF000000), 8) | Hex(((&''valore'' \ CInt(2 ^ 24)) And &FF) Or ((&''valore'' * CInt(2 ^ 8)) And &FF0000) Or CShort(((&''valore'' \ CInt(2 ^ 8)) And &FF00)) Or ((&''valore'' * CInt(2 ^ 24)) And &FF000000), 8) | ||
− | + | ==Uso dell'operatore ''OR'' con operazione di scorrimento dei bit a sinistra== | |
− | |||
Mostriamo un esempio pratico con l'operatore ''OR'' combinato con operazione di scorrimento dei bit a sinistra, in cui convertiremo il valore esadecimale ''0x67452301'' da ''Little-Endian'' a ''Big-Endian'': | Mostriamo un esempio pratico con l'operatore ''OR'' combinato con operazione di scorrimento dei bit a sinistra, in cui convertiremo il valore esadecimale ''0x67452301'' da ''Little-Endian'' a ''Big-Endian'': | ||
'''Public''' Sub Main() | '''Public''' Sub Main() | ||
Riga 106: | Riga 100: | ||
'''End''' | '''End''' | ||
Questo algoritmo è valido anche per la conversione contraria: da ''Big-Endian'' a ''Little-Endian''. | Questo algoritmo è valido anche per la conversione contraria: da ''Big-Endian'' a ''Little-Endian''. | ||
+ | |||
+ | |||
+ | =Rotazione dei byte mediante le funzioni ''ntohl( )'' e ''ntohs( )''= | ||
+ | Mediante le funzioni esterne ''ntohl( )'' e ''ntohs( )'', dichiarate nel file header "''/usr/include/netinet/in.h''", è possibile ottenere la rotazione dei byte rispettivamente di un valore di tipo ''Intero'' (32 bit) e di uno valore di tipo ''Intero Corto'' (16 bit). | ||
+ | |||
+ | Mostriamo un semplice esempio: | ||
+ | Library "libc:6" | ||
+ | <FONT Color=gray>' ''uint32_t ntohl (uint32_t __netlong)'' | ||
+ | ' ''Converts the unsigned integer netlong from network byte order to host byte order.''</font> | ||
+ | Private Extern ntohl(__netlong As Integer) As Integer | ||
+ | |||
+ | <FONT Color=gray>' ''uint16_t ntohs (uint16_t __netshort)'' | ||
+ | ' ''Converts the unsigned short integer netshort from network byte order to host byte order.''</font> | ||
+ | Private Extern ntohs(__netshort As Short) As Short | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
+ | Dim i As Integer | ||
+ | Dim c As Short | ||
+ | |||
+ | i = ntohl(&01020304) | ||
+ | Print Hex(i, 8) | ||
+ | |||
+ | c = ntohs(&0908) | ||
+ | Print Hex(c, 4) | ||
+ | |||
+ | '''End''' | ||
+ | |||
Versione delle 15:48, 10 feb 2017
Big-Endian e Little-Endian sono due differenti modalità per memorizzare dati di dimensione superiore al semplice byte.
La differenza tra i due sistemi è data dall'ordine, con il quale i byte costituenti il dato vengono memorizzati:
- Big-Endian è il tipo di memorizzazione che inizia (da sinistra verso destra) dal byte più significativo (che è quello posto a sinistra) e termina con il byte meno significativo;
- Little-Endian è il tipo di memorizzazione che inizia (da destra verso sinistra) dal byte meno significativo (che è quello posto a destra) e termina con il byte più significativo. Quindi in sostanza nel sistema Little-Endian l'ordine dei byte nell'indirizzo di memoria è invertito ripetto al sistema Big-Endian.
Se ad esempio abbiamo il valore decimale 1234567, la memorizzazione nella seguente forma esadecimale:
12 D6 87
è di tipo Big-Endian.
Invece la memorizzazione di quello stesso numero nella forma:
87 D6 12
è, invece, di tipo Little-Endian.
In taluni casi particolari, pertanto, possiamo riscontrare che alcuni valori vengono scritti per la memorizzazione in modalità Little-Endian, e che, pertanto, per comprenderne il reale significato/valore, devono essere convertiti in forma Big-Endian. Possiamo, per converso, avere valori che, memorizzati inizialmente nel formato esadecimale della forma Big-Endian, debbano essere convertiti in forma Little-Endian, affinché altri pogrammi possano comprendere il loro reale significato e restituire quindi il vero valore.
Indice
Conversione Big-Endian/Little-Endian e viceversa di un valore a 16bit
La formula astratta per ottenere la conversione Big-Endian/Little-Endian e viceversa di un valore a 16bit (= 2 byte, ossia di tipo Short) può essere la seguente (anche se le modalità sono molteplici per ottenere la conversione):
((valore >> 8) & 0x00FF) | ((valore << 8) & 0xFF00)
che in Gambas potremo tradurre, utilizzando uno dei seguenti metodi:
- funzioni di scorrimento dei bit a destra ed a sinistra;
- esplicite operazioni matematiche;
- Uso dell'operatore OR combinato con operazione di scorrimento dei bit a sinistra.
Uso delle funzioni di scorrimento dei bit a destra ed a sinistra
Questa modalità è in sintassi così espressa:
Hex((Shr(&valore, 8) And &FF) Or (Shl(&valore, 8) And &FF00&), 4) As String
Se valore è proprio una variabile di tipo Short, allora il suo valore va convertito in decimale, ad esempio così:
Val("&" & valore).
V'è da sottolineare che il il valore &FF00& necessita assolutamente alla fine del carattere &, poiché, se non lo si ponesse, avremmo come risultato un valore in esadecimale di 3 byte ! [ Nota 1 ]
Uso di esplicite operazioni matematiche
Se si vorranno utilizzare esplicite operazioni matematiche anziché funzioni Gambas, si potrà adoperare la seguente formula:
Hex(((&valore \ CInt(2 ^ 8)) And &FF) Or ((&valore * CInt(2 ^ 8)) And &FF00&), 4) As String
oppure
Hex(((&valore \ CInt(2 ^ 8)) And &FF) Or CShort(((&valore * CInt(2 ^ 8)) And &FF00)), 4) As String
Uso dell'operatore OR con operazione di scorrimento dei bit a sinistra
Mostriamo un esempio pratico con l'operatore OR combinato con operazione di scorrimento dei bit a sinistra, in cui convertiremo il valore esadecimale 0x2301 di tipo Short da Little-Endian a Big-Endian:
Public Sub Main() Dim valore, s1, s2, v As Short valore = &2301 s1 = Shr(valore, 8) s2 = valore And 255 v = s1 v = v Or Shl(s2, 8) Print Hex(v, 4), v End
Questo algoritmo è valido anche per la conversione contraria: da Big-Endian a Little-Endian.
Conversione Big-Endian/Little-Endian e viceversa di un valore a 32bit
La formula astratta per ottenere la conversione Big-Endian/Little-Endian di un valore a 32bit (= 4 byte, ossia di tipo Integer) può essere la seguente:
((valore >> 24) & 0xff) | ((valore << 8) & 0xff0000) | ((valore >> 8) & 0xff00) | ((valore << 24) & 0xff000000)
che in Gambas potremo tradurre, utilizzando uno dei seguenti metodi:
- funzioni di scorrimento dei bit a destra ed a sinistra;
- esplicite operazioni matematiche;
- Uso dell'operatore OR combinato con operazione di scorrimento dei bit a sinistra.
Uso delle funzioni di scorrimento dei bit a destra ed a sinistra
Questa modalità è in sintassi così espressa:
Hex((Shr(&valore, 24) And &FF) Or (Shl(&valore, 8) And &FF0000) Or (Shr(&valore, 8) And &FF00&) Or (Shl(&valore, 24) And &FF000000), 8) A String
Uso di esplicite operazioni matematiche
Se si vorranno utilizzare esplicite operazioni matematiche anziché funzioni Gambas, si potrà adoperare la seguente formula:
Hex(((&valore \ CInt(2 ^ 24)) And &FF) Or ((&valore * CInt(2 ^ 8)) And &FF0000) Or ((&valore \ CInt(2 ^ 8)) And &FF00&) Or ((&valore * CInt(2 ^ 24)) And &FF000000), 8)
oppure quest'altra:
Hex(((&valore \ CInt(2 ^ 24)) And &FF) Or ((&valore * CInt(2 ^ 8)) And &FF0000) Or CShort(((&valore \ CInt(2 ^ 8)) And &FF00)) Or ((&valore * CInt(2 ^ 24)) And &FF000000), 8)
Uso dell'operatore OR con operazione di scorrimento dei bit a sinistra
Mostriamo un esempio pratico con l'operatore OR combinato con operazione di scorrimento dei bit a sinistra, in cui convertiremo il valore esadecimale 0x67452301 da Little-Endian a Big-Endian:
Public Sub Main() Dim valore, i1, i2, i3, i4, v As Integer valore = &67452301 i1 = Shr(valore, 24) i2 = Shl(valore, 16) And 255 i3 = Shr(valore, 8) And 255 i4 = valore And 255 v = i1 v = v Or Shl(i2, 8) v = v Or Shl(i3, 16) v = v Or Shl(i4, 24) Print Hex(v, 8), v End
Questo algoritmo è valido anche per la conversione contraria: da Big-Endian a Little-Endian.
Rotazione dei byte mediante le funzioni ntohl( ) e ntohs( )
Mediante le funzioni esterne ntohl( ) e ntohs( ), dichiarate nel file header "/usr/include/netinet/in.h", è possibile ottenere la rotazione dei byte rispettivamente di un valore di tipo Intero (32 bit) e di uno valore di tipo Intero Corto (16 bit).
Mostriamo un semplice esempio:
Library "libc:6" ' uint32_t ntohl (uint32_t __netlong) ' Converts the unsigned integer netlong from network byte order to host byte order. Private Extern ntohl(__netlong As Integer) As Integer ' uint16_t ntohs (uint16_t __netshort) ' Converts the unsigned short integer netshort from network byte order to host byte order. Private Extern ntohs(__netshort As Short) As Short Public Sub Main() Dim i As Integer Dim c As Short i = ntohl(&01020304) Print Hex(i, 8) c = ntohs(&0908) Print Hex(c, 4) End
Note
[1] Interpellato al riguardo Benoît Minisini ha così spiegato il problema e suggerito la soluzione:
« Because of weird Visual Basic compatibility, &FF00 is sign-extended, i.e. &FF00 = &FFFFFF00
To prevent automatic sign-extension, write &FF00& (with an extra '&' at the end).
Otherwise, I don't know where your data comes from, but Swap$() does endianness conversion provided that each integer is stored inside a string. »