## Big Endian -> Little Endian

General FreeBASIC programming questions.
BasicScience
Posts: 489
Joined: Apr 18, 2008 4:09
Location: Los Angeles, CA
Contact:

### Big Endian -> Little Endian

Trying to read 32-bit floating point numbers from a binary data file created by LabView. Apparently LabView uses Big Endian since it was originally developed on a Mac OS. Anyone have a fast Big Endian -> Little Endian converter (to work on single float variable or array of single float)?
MrSwiss
Posts: 3634
Joined: Jun 02, 2013 9:27
Location: Switzerland

### Re: Big Endian -> Little Endian

Some endian swapping Macros. However, they are geared towards
ULong / ULongInt and not Single ... (if I've correctly interpreted, the question).

This could be solved, with a Union:

Code: Select all

`Union DW    As Single  sdw    As ULong   uldwEnd Union`
Last edited by MrSwiss on Jul 24, 2018 20:32, edited 1 time in total.
srvaldez
Posts: 2543
Joined: Sep 25, 2005 21:54

### Re: Big Endian -> Little Endian

here some discussion on big endian to little endian conversion viewtopic.php?f=3&t=25857&p=235216&hilit=big+endian#p235216
also more specifically dealing with float https://stackoverflow.com/questions/278 ... tle-endian
the answer by Gregor Brandt converted to FB

Code: Select all

`'by Gregor Brandtfunction ReverseFloat(byval inFloat as const single) as single   dim retVal as single   dim floatToConvert as zstring ptr = cptr(zstring ptr, @inFloat)   dim returnFloat as zstring ptr = cptr(zstring ptr, @retVal)   returnFloat[0] = floatToConvert[3]   returnFloat[1] = floatToConvert[2]   returnFloat[2] = floatToConvert[1]   returnFloat[3] = floatToConvert[0]   return retValend function`
BasicScience
Posts: 489
Joined: Apr 18, 2008 4:09
Location: Los Angeles, CA
Contact:

### Re: Big Endian -> Little Endian

Thanks for the ideas.

@sarvaldez, I get a segment violation error at this line:

returnFloat[0] = floatToConvert[3]

Is Callocate needed to set aside memory for the arrays?
fxm
Posts: 9993
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Big Endian -> Little Endian

Warning:
This above function writes at least 4 additional bytes behind the Single due to a misuse of Zstring.

IMHO, use 'Byte Ptr' instead of 'Zstring Ptr':

Code: Select all

`function ReverseFloat(byval inFloat as const single) as single   dim retVal as single   dim floatToConvert as byte ptr = cptr(byte ptr, @inFloat)   dim returnFloat as byte ptr = cptr(byte ptr, @retVal)   returnFloat[0] = floatToConvert[3]   returnFloat[1] = floatToConvert[2]   returnFloat[2] = floatToConvert[1]   returnFloat[3] = floatToConvert[0]   return retValend function`
jevans4949
Posts: 1156
Joined: May 08, 2006 21:58
Location: Crewe, England

### Re: Big Endian -> Little Endian

Some stuff I wrote a while back, using asm. (To do with MIDI files)

Code: Select all

`'***********************************************************************' Big-endian integer Handling'***********************************************************************#include once "jevans4949/bigend/bigend.bi"'***********************************************************************' Big-endian Operator Functions'***********************************************************************operator be4.cast() as integer    asm        mov eax,[This]        mov eax,[eax]        bswap eax        mov [function],eax    end asmend operator'operator be4.let(byval source as integer)    asm        mov ebx,[this]       mov eax,[source]        bswap eax        mov [ebx],eax    end asmend operator'operator be2s.cast() as integer   asm       mov ebx,[This]       movsxb eax,Byte Ptr[ebx]       sal eax,8       mov al,[ebx+1]       mov [Function],eax   end asmend operator'operator be2s.let(byval source as integer)    asm        mov ebx,[This]       mov eax,[source]        mov [ebx],ah        mov [ebx+1],al    end asmend operator'operator be2u.cast() as integer   asm       mov ebx,[This]       movzx eax,Byte Ptr[ebx]       sal eax,8       mov al,[ebx+1]       mov [Function],eax   end asmend operator'operator be2u.let(byval source as integer)    asm        mov ebx,[This]       mov eax,[source]        mov [ebx],ah        mov [ebx+1],al    end asmend operator'operator be3s.cast() as integer    asm        mov ebx,[This]        movsxb eax,Byte ptr[ebx]        sal eax,16        mov ah,[ebx+1]        mov al,[ebx+2]        mov [Function],eax   end asmend operator'operator be3s.let(byval source as integer)    asm        mov ebx,[This]       mov eax,[source]        mov [ebx+1],ah        mov [ebx+2],al        sar eax,8        mov [ebx],ah    end asmend operator'operator be3u.cast() as integer    asm        mov ebx,[This]        movzx eax,Byte ptr[ebx]        sal eax,16        mov ah,[ebx+1]        mov al,[ebx+2]        mov [Function],eax   end asmend operator'operator be3u.let(byval source as integer)    asm        mov ebx,[This]       mov eax,[source]        mov [ebx+1],ah        mov [ebx+2],al        sar eax,8        mov [ebx],ah    end asmend operator`

Here's the include:

Code: Select all

`'***********************************************************************' Stuff to pull in lib's'***********************************************************************#if (__FB_OUT_LIB__ = 0)#libpath "/freebasic/lib/win32/jevans4949/bigend"#inclib "bigend"#endif'***********************************************************************' Big-endian Type definitions'***********************************************************************type be4 field=1                        '4 byte,assumed signed    i as integer    declare operator cast() as integer    declare operator let(source as integer)end type'type be3s field=1                       '3 byte signed     as ubyte h,m,l    declare operator cast() as integer    declare operator let(source as integer)end type'type be3u field=1                       '3 byte unsigned     as ubyte h,m,l    declare operator cast() as integer    declare operator let(source as integer)end type'type be2s field=1                       '2 byte signed     i as short    declare operator cast() as integer    declare operator let(source as integer)end type'type be2u field=1                       '2 byte unsigned     i as ushort    declare operator cast() as integer    declare operator let(source as integer)end type'`

And here's a test driver

Code: Select all

`'***********************************************************************' Big-endian integer Handling'***********************************************************************#include once "jevans4949/bigend/bigend.bi"'***********************************************************************' Big-Endian Test Harness'***********************************************************************dim p as ubyte ptrdim i as integerdim j as integerdim x as be4dim y as be3sdim z as be2sdim w as be2udim v as be3uloop1:Input "Enter value of type long";ix = iy = iz = iw = iv = ip=@xprint "converted to be4: ";hex(*p,2);hex(*(p+1),2);hex(*(p+2),2);hex(*(p+3),2)p=@yprint "converted to be3s: ";hex(*p,2);hex(*(p+1),2);hex(*(p+2),2)p=@vprint "converted to be3u: ";hex(*p,2);hex(*(p+1),2);hex(*(p+2),2)p=@zprint "converted to be2s: ";hex(*p,2);hex(*(p+1),2)p=@wprint "converted to be2u: ";hex(*p,2);hex(*(p+1),2)j = xprint "Converted back from be4:  ";jj = yprint "Converted back from be3s: ";jj = vprint "Converted back from be3u: ";jj = zprint "Converted back from be2s: ";jj = wprint "Converted back from be2u: ";jgoto loop1`

You probably need to define your fields as a Union of Singles and Longs/be4 to get this to work.

Enjoy
BasicScience
Posts: 489
Joined: Apr 18, 2008 4:09
Location: Los Angeles, CA
Contact:

### Re: Big Endian -> Little Endian SOLVED

@fxm, thanks for catching ptr issue with Zstring. With your byte ptr modification, the code runs correctly.

@jevans I'll do some timing tests, and then consider diving into your asm version.

Thanks to all
jj2007
Posts: 1726
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

### Re: Big Endian -> Little Endian

Didn't know there are "big endian" floats around... but conversion is pretty simple, this snippet converts it twice:

Code: Select all

`dim as single MySingle = 123.456Sub SwitchEndians(TheFloat As Single ptr)  Asm   mov edx, [TheFloat]   mov eax, [edx]   bswap eax   mov [edx], eax  End AsmEnd Subprint "float=";MySingleSwitchEndians(@MySingle)print "float=";MySingleSwitchEndians(@MySingle)print "float=";MySinglesleep()`
MrSwiss
Posts: 3634
Joined: Jun 02, 2013 9:27
Location: Switzerland

### Re: Big Endian -> Little Endian

A simple pure FB Function, using UByte Ptr:

Code: Select all

`' eSwpSgl_Func.bas -- 2018-07-24, by MrSwiss'' compile: -s console'Function eSwpSgl(ByVal si As Const Single) As Single    Dim As Single   ret    For i As UInteger = 0 To 3        CPtr(UByte Ptr, @ret)[3 - i] = CPtr(UByte Ptr, @si)[i]    Next    Return retEnd FunctionDim As Single   ts1 = 1.0, ts2 = -5.0, tr1 = 0.0, tr2 = 0.0Print ts1,, ts2                         ' show start valuestr1 = eSwpSgl(ts1) : tr2 = eSwpSgl(ts2) ' endiannes swapPrint tr1, tr2                          ' show resultts1 = 0.0 : ts2 = 0.0                   ' clear vars. (for return of reverse operation)ts1 = eSwpSgl(tr1) : ts2 = eSwpSgl(tr2) ' reverse endiannes swapPrint ts1,, ts2                         ' show reverse resultSleep`
BasicScience
Posts: 489
Joined: Apr 18, 2008 4:09
Location: Los Angeles, CA
Contact:

### Re: Big Endian -> Little Endian

@jj2007 - your ASM conversion is the fastest of the suggested approaches. I suppose this code would work for any 32-bit value (e.g. even for long integer)? It's been a while since I wrote code ASM, what modification would be needed for a 16 bit value (e.g. short integer)?
jj2007
Posts: 1726
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

### Re: Big Endian -> Little Endian

BasicScience wrote:what modification would be needed for a 16 bit value (e.g. short integer)?

Code: Select all

`  bswap eax  shr eax, 16`
jevans4949
Posts: 1156
Joined: May 08, 2006 21:58
Location: Crewe, England

### Re: Big Endian -> Little Endian

jj2007 has the simplest answer for Singles or 4-byte integers - well done!

My code contains solutions for 2- and 3-byte signed and unsigned integers.

Note, however, that my code assumes a 32-bit compile - assumes sizeof(integer) and sizeof(pointer), and does not include 64-bit integers at all. Obviously it wouldn't work a non-Intel/AMD target either.
jj2007
Posts: 1726
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

### Re: Big Endian -> Little Endian

jevans4949 wrote:jj2007 has the simplest answer for Singles or 4-byte integers - well done!
Thanks.

My code contains solutions for 2- and 3-byte signed and unsigned integers.
Interesting. The FPU can handle 2-byte (as in fild word ptr [esp]), 4-byte and 8-byte integers, but I've never heard of a 3-byte integer. Technically, it can be done, of course:

Code: Select all

`  bswap eax  shr eax, 8`
... but is there any IEEE 754 norm about 3-byte integers? Just curious...
jevans4949
Posts: 1156
Joined: May 08, 2006 21:58
Location: Crewe, England

### Re: Big Endian -> Little Endian

jj2007 wrote:... but I've never heard of a 3-byte integer ...

The MIDI fie specification includes one instance of 3-byte integer, and also wierd variable-length integers - lower 7 bits of each byte are data and top bit indicates another byte follows - e.g &h'8307' decodes to &h'0187'. All integers are big-endian.

EDIT: I once woked for a financial analysis company that had defined a 2-byte compressed float for company accounts data! Can't now remeber the details.
Last edited by jevans4949 on Jul 27, 2018 1:01, edited 1 time in total.
jj2007
Posts: 1726
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

### Re: Big Endian -> Little Endian

Wow, that's funny. Since it's MIDI, I wonder whether the Atari folks were involved. In the meantime I got curious and found out that apparently some graphics cards use a 24-bit float format. I never stop learning ;-)