It is currently Fri Jan 18, 2019 11:23 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: Simple Big Endian / Little Endian byte order swap function.
PostPosted: Thu Mar 24, 2005 8:30 am 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2005 5:05 pm
Posts: 1769
Location: Norway
Ever needed to swap the byte order when working with LittleEndian and BigEndian values?

Here is a quick solution.

32bit value swap
Code:
Procedure.l Endian(val.l)
!MOV Eax,dword[p.v_val]
!BSWAP Eax
ProcedureReturn
EndProcedure


Example:
Code:
Debug Hex(Endian($112233))


64bit value swap (PS! the ordering (pairing) of instructions is in an attempt to support hyper threading and similar)
Code:
CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
   Procedure.q EndianQ(val.q)
   !MOV rax,qword[p.v_val]
   !BSWAP rax
   ProcedureReturn
   EndProcedure
CompilerElse
   Procedure.q EndianQ(val.q)
   !MOV Eax,dword[p.v_val]
   !MOV Edx,dword[p.v_val+4]
   !BSWAP Eax
   !BSWAP Edx
   !MOV dword[p.v_val+4],Eax
   !MOV dword[p.v_val],Edx
   ProcedureReturn val
   EndProcedure
CompilerEndIf


Example:
Code:
Debug Hex(EndianQ($112233))


Now you can just do things like color=Endian(color)
if you need to convert to/from RGB,BGR or RGBA and ABGR etc.

Or when dealing with network order/Motorola (big endian) values.

EDIT: PB 4.x implementations instead, the older PB 3.x functions moved to the 2nd post.

Sidenote to Fred: Endian() and EndianQ() really need to be native PB commands :P

Have fun!


Last edited by Rescator on Sun Nov 22, 2009 6:33 am, edited 10 times in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Mar 24, 2005 9:17 am 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2005 5:05 pm
Posts: 1769
Location: Norway
***Older PB 3.x functions***

Code:
Procedure.l Endian(dummy.l)
!BSWAP Eax
ProcedureReturn
EndProcedure

And here is how to do Little/Big Endian byte swapping with 64bit values.

Code:
Procedure.l Endian64(*val.LARGE_INTEGER)
 h.l=Endian(*val\HighPart)
 l.l=Endian(*val\LowPart)
 *val\HighPart=l
 *val\LowPart=h
ProcedureReturn *val
EndProcedure


Example of use:
Code:
b.LARGE_INTEGER
b\HighPart=$BB0220
b\LowPart=$AA0110

Debug Hex(b\HighPart)
Debug Hex(b\LowPart)

Endian64(b)

Debug Hex(b\HighPart)
Debug Hex(b\LowPart)


Here is a assembler implementation of Endian64()

Code:
Procedure.l Endian64(*dummy)
!MOV Ebx,[Eax]
!MOV Edx,[Eax+4]
!BSWAP Ebx
!BSWAP Edx
!MOV [Eax+4],Ebx
!MOV [Eax],Edx
ProcedureReturn
EndProcedure


Have fun :)

Code:
b.LARGE_INTEGER
b\HighPart=$BB0220
b\LowPart=$AA0110

Debug Hex(b\HighPart)
Debug Hex(b\LowPart)

Endian64(b)

Debug Hex(b\HighPart)
Debug Hex(b\LowPart)


Last edited by Rescator on Thu Aug 17, 2006 4:43 pm, edited 3 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap function.
PostPosted: Sun Nov 22, 2009 6:30 am 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2005 5:05 pm
Posts: 1769
Location: Norway
Updated first post, x64 support and speedup.


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap function.
PostPosted: Sun Nov 22, 2009 12:07 pm 
Offline
Addict
Addict
User avatar

Joined: Sat Aug 15, 2009 6:59 pm
Posts: 1249
Yes, bswap is pretty usefull. But the ordering of instructions have nothing to do with hyperthreading. The CPU can execute up to 3 instructions in parallel because it have 3 instruction pipelines (2 on older CPU's). That have nothing to do with threads. You can use threads in addition to the instruction ordering.

In fact there are 3 distinct parallelization layers. First you can parallelize by using SIMD instructions, which can process 4 doublewords or 8 words or 16 bytes in parallel. Second you can order the instructions, you even can order SIMD instructions so a maximum of 3 SIMD instructions is executed in parallel. And third you can use threads.


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap function.
PostPosted: Mon Nov 23, 2009 8:27 am 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2005 5:05 pm
Posts: 1769
Location: Norway
That's an old comment, I think what I meant at the time was dual pipelining, I think it was Intel Pentium 4 (!) that added some stuff for that while at the time AMD had not yet.

Shame phhpBB3 doesn't have a strike through tag or I'd use that to strike out that comment. :)


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Sat May 07, 2011 12:32 am 
Offline
Addict
Addict
User avatar

Joined: Wed Dec 23, 2009 10:14 pm
Posts: 2810
Location: Boston, MA
Thanks Rescator!
I agree this should be a native command. :idea:

So, I needed to swap a 16 bit word...
I am ashamed to say how much reading/fumbling along to come up with this... :oops:
But now I have a whole bunch of ASM urls for next time... :lol:

Code:
Procedure.w EndianW(val.w)
  !MOV ax, word[p.v_val]
  !XCHG al, ah                ; Swap Lo byte <-> Hi byte
  !MOV word[p.v_val], ax
  ProcedureReturn val
EndProcedure

_________________
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Mon Sep 19, 2011 3:48 pm 
Offline
Addict
Addict

Joined: Sat Apr 10, 2004 1:20 pm
Posts: 1143
Location: Germany
Thanks Rescator / skywalk for this very usefull Tip.

I am currently using it in PurePDF.

I hope its working on all three Platforms ? (Win / Linux / MacOS)

BR Klaus


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Mon Sep 19, 2011 4:40 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3287
Location: Netherlands
ABBKlaus wrote:
I hope its working on all three Platforms ? (Win / Linux / MacOS)

No, that won't work on OS X.
There's a bug on OS X with labels of local variables like [p.v_val].
What should work on all three platforms is using EnableASM.
Here's two alternatives
Code:
Procedure.w EndianW(val.w)
  EnableASM
  ROL val, 8
  DisableASM
  ProcedureReturn val
EndProcedure

Code:
Procedure.w EndianW(val.w)
  EnableASM
  MOV ax, val
  XCHG al, ah
  DisableASM
  ProcedureReturn
EndProcedure


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Mon Sep 19, 2011 5:51 pm 
Offline
Addict
Addict

Joined: Sat Apr 10, 2004 1:20 pm
Posts: 1143
Location: Germany
Thanks wilbert,

i have changed the above procedures for EndianW() and EndianL() :

Code:
Procedure.w ipf_EndianW(value.w)
  EnableASM
  ROL value, 8
  DisableASM
  ProcedureReturn value
EndProcedure

Code:
Procedure.l ipf_EndianL(value.l)
  EnableASM
  MOV Eax,value
  BSWAP Eax
  DisableASM
  ProcedureReturn
EndProcedure


but what about EndianQ() ?


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Mon Sep 19, 2011 6:54 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3287
Location: Netherlands
EndianQ is a bit more complicated but here are two ways.
Code:
Procedure.q EndianQ(val.q)
  EnableASM
  MOVQ mm0, val
  MOVD edx, mm0
  BSWAP edx
  PSRLQ mm0, 32
  MOVD eax, mm0
  BSWAP eax
  EMMS
  DisableASM
  ProcedureReturn
EndProcedure

Code:
Procedure.q EndianQ(val.q)
  Protected addr.l = @val
  EnableASM
  MOV edx, addr
  MOV eax, [edx + 4]
  MOV edx, [edx]
  BSWAP eax
  BSWAP edx
  DisableASM
  ProcedureReturn
EndProcedure

The first one doesn't need an extra variable but uses a mmx register, the second one is plain asm but requires an extra protected variable.


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Mon Sep 19, 2011 10:10 pm 
Offline
Addict
Addict
User avatar

Joined: Wed Dec 23, 2009 10:14 pm
Posts: 2810
Location: Boston, MA
Thanks wilbert.
I don't have a Mac. Is this what you are saying does not work?
http://www.purebasic.com/documentation/reference/inlinedasm.html wrote:
- It's possible to pass directly an assembly line to the assembler without being processed by the compiler by using the '!' character at the line start. This allow to have a full access to the assembler directives. When using this, it's possible to reference the local variables using the notation 'p.v_variablename' for a regular variable or 'p.p_variablename' for a pointer

_________________
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Tue Sep 20, 2011 5:31 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3287
Location: Netherlands
When you enable asm with EnableASM, you can use a variable name directly otherwise you have to use the p.v_variablename .
I would prefer the p.v_variablename since it's more versatile but there's a bug with that on OS X.

It's kind of a nightmare at the moment on OS X to use variables with inline ASM.
The p.v_variablename isn't working and using the stack pointer directly like esp+4 also isn't reliable since the offset from the stack pointer where the variable is located is different from that on windows because of some extra code the PB compiler adds.
I mentioned the bug with the p.v_variablename syntax in the OS X bugs forum but unfortunately it hasn't been fixed yet.

It probably only would be a matter of one minute. If you look at the ASM source, it currently says
Code:
%define p. v_valesp+PS0+0
instead of
Code:
%define p.v_val esp+PS0+0

so the only problem is that the space character is on the wrong place.
But it's not something I can fix :(


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Tue Sep 20, 2011 11:53 am 
Offline
Addict
Addict

Joined: Sat Apr 10, 2004 1:20 pm
Posts: 1143
Location: Germany
Thanks wilbert, i have taken your second approach for PurePDF :wink:


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Tue Sep 20, 2011 3:53 pm 
Offline
Addict
Addict
User avatar

Joined: Wed Dec 23, 2009 10:14 pm
Posts: 2810
Location: Boston, MA
wilbert wrote:
If you look at the ASM source, it currently says
Code:
%define p. v_valesp+PS0+0
instead of
Code:
%define p.v_val esp+PS0+0

so the only problem is that the space character is on the wrong place.

Thanks for the details.
I bet Fred wishes all his bugs were this easy :D


Top
 Profile  
Reply with quote  
 Post subject: Re: Simple Big Endian / Little Endian byte order swap functi
PostPosted: Thu Sep 22, 2011 2:52 pm 
Offline
TailBite Expert
TailBite Expert

Joined: Fri Apr 25, 2003 6:09 pm
Posts: 1007
Location: Spain
I would use macros instead of procedures for speed's sake.

_________________
El_Choni


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye