Page 1 of 2
					
				Simple Big Endian / Little Endian byte order swap function.
				Posted: Thu Mar 24, 2005 8:30 am
				by Rescator
				Ever needed to swap the byte order when working with LittleEndian and BigEndian values?
Here is a quick solution.
32bit value swap
Code: Select all
Procedure.l Endian(val.l)
!MOV Eax,dword[p.v_val]
!BSWAP Eax
ProcedureReturn
EndProcedure
Example: 
64bit value swap (PS! the ordering (pairing) of instructions is in an attempt to support hyper threading and similar)
Code: Select all
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: 
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 
Have fun!
 
			 
			
					
				
				Posted: Thu Mar 24, 2005 9:17 am
				by Rescator
				***Older PB 3.x functions***
Code: Select all
Procedure.l Endian(dummy.l)
!BSWAP Eax
ProcedureReturn
EndProcedure
And here is how to do Little/Big Endian byte swapping with 64bit values.
Code: Select all
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: Select all
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: Select all
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: Select all
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) 
 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap function.
				Posted: Sun Nov 22, 2009 6:30 am
				by Rescator
				Updated first post, x64 support and speedup.
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap function.
				Posted: Sun Nov 22, 2009 12:07 pm
				by Thorium
				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.
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap function.
				Posted: Mon Nov 23, 2009 8:27 am
				by Rescator
				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. 

 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Sat May 07, 2011 12:32 am
				by skywalk
				Thanks Rescator!
I agree this should be a native command.  
So, I needed to swap a 16 bit word...
I am ashamed to say how much reading/fumbling along to come up with this...  
 
But now I have a whole bunch of ASM urls for next time...  
 
Code: Select all
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
 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Mon Sep 19, 2011 3:48 pm
				by ABBKlaus
				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
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Mon Sep 19, 2011 4:40 pm
				by wilbert
				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: Select all
Procedure.w EndianW(val.w)
  EnableASM
  ROL val, 8
  DisableASM
  ProcedureReturn val
EndProcedure
 
Code: Select all
Procedure.w EndianW(val.w)
  EnableASM
  MOV ax, val
  XCHG al, ah
  DisableASM
  ProcedureReturn
EndProcedure
 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Mon Sep 19, 2011 5:51 pm
				by ABBKlaus
				Thanks wilbert,
i have changed the above procedures for EndianW() and EndianL() :
Code: Select all
Procedure.w ipf_EndianW(value.w)
  EnableASM
  ROL value, 8
  DisableASM
  ProcedureReturn value
EndProcedure
 
Code: Select all
Procedure.l ipf_EndianL(value.l)
  EnableASM
  MOV Eax,value
  BSWAP Eax
  DisableASM
  ProcedureReturn
EndProcedure
but what about EndianQ() ?
 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Mon Sep 19, 2011 6:54 pm
				by wilbert
				EndianQ is a bit more complicated but here are two ways.
Code: Select all
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: Select all
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.
 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Mon Sep 19, 2011 10:10 pm
				by skywalk
				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
 
 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Tue Sep 20, 2011 5:31 am
				by wilbert
				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
instead of
so the only problem is that the space character is on the wrong place.
But it's not something I can fix  

 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Tue Sep 20, 2011 11:53 am
				by ABBKlaus
				Thanks wilbert, i have taken your second approach for PurePDF  

 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Tue Sep 20, 2011 3:53 pm
				by skywalk
				wilbert wrote:If you look at the ASM source, it currently says
instead of
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  

 
			 
			
					
				Re: Simple Big Endian / Little Endian byte order swap functi
				Posted: Thu Sep 22, 2011 2:52 pm
				by El_Choni
				I would use macros instead of procedures for speed's sake.