Differenze tra le versioni di "Conversione Big-Endian/Little-Endian"

Da Gambas-it.org - Wikipedia.
Riga 41: Riga 41:
  
 
===Uso dell'operatore ''OR'' con operazione di scorrimento dei bit a sinistra===
 
===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 ''&2301'' 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'' da ''Little-Endian'' a ''Big-Endian'':
 
  '''Public''' Sub Main()
 
  '''Public''' Sub Main()
 
   
 
   
Riga 59: Riga 59:
 
   
 
   
 
  '''End'''
 
  '''End'''
Questo algortmo è valido anche per la converione contraria: da 'Big-Endian'' a ''Little-Endian''.
+
Questo algoritmo è valido anche per la conversione contraria: da 'Big-Endian'' a ''Little-Endian''.
  
  
  
==Conversione ''Big-Endian''/''Little-Endian'' di un valore a 32bit==
+
==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)
che in Gambas potremo tradurre quella formula, utilizzando le funzioni di scorrimento dei bit a destra ed a sinistra, in sintassi così:
+
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
 
  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)
 
oppure quest'altra:
 
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)
 
  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()
 +
 +
  Public Sub Main()
 +
 +
  Dim valore As String = ''67452301''
 +
  Dim i1, i2, i3, i4, v As Integer
 +
 
 +
 +
  i1 = CInt(Val("&" & Left(valore, 2)))
 +
  i2 = CInt(Val("&" & Mid(valore, 3, 2)))
 +
  i3 = CInt(Val("&" & Mid(valore, 5, 2)))
 +
  i4 = CInt(Val("&" & Right(valore, 2)))
 +
  v = i1
 +
  v = v Or i2 * (CInt(2 ^ 8))
 +
  v = v Or i3 * (CInt(2 ^ 16))
 +
  v = v Or i4 * (CInt(2 ^ 24))
 +
 +
  Print Hex(v, 8)
 +
 +
'''End'''
 +
Questo algoritmo è valido anche per la conversione contraria: da 'Big-Endian'' a ''Little-Endian''.
 
   
 
   
  

Versione delle 10:23, 21 gen 2014

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 destra verso sinistra) dal byte più significativo e termina con il byte meno significativo;
  • Little-Endian è il tipo di memorizzazione che inizia (da destra verso sinistra) dal byte meno significativo e termina con il byte più significativo.

Se ad esempio abbiamo il valore decimale 1234567, la memorizzazione nella seguente forma:

12 D6 87

è di tipo Big-Endian, mentre una memorizzazione 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.


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 ! |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 da Little-Endian a Big-Endian:

Public Sub Main()

 Dim valore As String = "2301"
 Dim b1, b2, v As Short
 Dim s As String


  b1 = CShort(Val("&" & Left(valore, 2)))

  b2 = CShort(Val("&" & Right(valore, 2)))

  v = b1
  v = v Or b2 * (CInt(2 ^ 8))
   
  Print Hex(v, 4)

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()

 Public Sub Main()

 Dim valore As String = 67452301
 Dim i1, i2, i3, i4, v As Integer
  

  i1 = CInt(Val("&" & Left(valore, 2)))
  i2 = CInt(Val("&" & Mid(valore, 3, 2)))
  i3 = CInt(Val("&" & Mid(valore, 5, 2)))
  i4 = CInt(Val("&" & Right(valore, 2)))
  v = i1
  v = v Or i2 * (CInt(2 ^ 8))
  v = v Or i3 * (CInt(2 ^ 16))
  v = v Or i4 * (CInt(2 ^ 24))

  Print Hex(v, 8)

End

Questo algoritmo è valido anche per la conversione contraria: da 'Big-Endian a Little-Endian.


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. »


Riferimenti