[TriLUG] Ten Little ENDIANS

Brian Weaver weave at oculan.com
Mon Mar 24 15:34:49 EST 2003


This routine should byte swap a 64-bit number from little endian to big
endian, and back again.

The basics are to swap long[0] with long[1] and then perform a ntohl on
each.

long long swap_64(register long long val)
{
	register long tmp = *((long *)&val);
	*((long *)&val) = *((long *)&val + 1);
	*((long *)&val + 1) = tmp;

	*((long *)&val) = ntohl(*((long *)&val));
	*((long *)&val + 1) = ntohl(*((long *)&val + 1);

	return val;
}

it could be done without additional function calls using something like
the function below. It should loop 4 times. You could take the loop
logic out if you so inclined.

long long swap_64(register long long val)
{
	register unsigned char *p = (unsigned char *)&val;
	register unsigned char *q = (unsigned char *)&val + sizeof(long long) -
1;
	register unsigned char xchg;

	do
	{
		xchg = *p;
		*p = *q;
		*q = xchg;
	} while(++p < --q);

	return val;
}

-Weave	
	

On Mon, 2003-03-24 at 10:19, Tarus Balog wrote:
> Gang:
> 
> I need some help with C on Solaris/Intel. Since this post is long and
> slightly off-topic, feel free to hit delete now.
> 
> OpenNMS is written in Java, but because Java does not have an ICMP API
> (which is important in network management) one was written in C and is
> accessed via JNI.
> 
> Processors come in two main types with respect to byte order. Those that
> list the most significant byte first are BIG_ENDIAN, whereas those that
> list the least significant byte first are LITTLE_ENDIAN. Network data is
> by default BIG_ENDIAN, regardless of the processor used.
> 
> Most RISC processors, like the SPARC, are BIG_ENDIAN, whereas Intel
> processors are LITTLE_ENDIAN. This means that on Intel you have to swap
> bytes received from the network in order for them to make sense.
> 
> We do this in the following code by creating a "network to host" macro.
> Most LITTLE_ENDIAN systems seem to support the conversion of "long"
> variable types, but don't seem to have macros for 64 bit "long long"
> variable types, so we create our own: ntohll (network to host long long)
> and htonll (host to network long long). Here's part of the code:
> 
> #if defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN) ||
> defined(__LITTLE_ENDIAN__)
> # ifndef ntohll
> #  if defined(__DARWIN__)
> #   define ntohll(_x_) NXSwapBigLongLongToHost(_x_)
> #  else
> #   define ntohll(_x_) __bswap_64(_x_)
> #  endif
> # endif
> 
> For BIG_ENDIAN systems, it is just a null macro.
> 
> Now, notice that on DARWIN (Mac OS X) there is already a function defined
> (where Ben Reed found it is beyond me as it is almost a googlewhack). On
> Linux the function is __bswap_64.
> 
> So, my first try was to search for an equivalent function to __bswap_64 in
> Solaris. No such luck. The "swab" function has potential, but I can't seem
> to get it to work.
> 
> Then my next attempt was to get the GNU byteswap.h code to work on
> Solaris/Intel. It compiles, but when I run it I get an undefined symbol
> error on "__udivdi3".
> 
> This is supposed to be included in libgcc.a, which I now have symbolically
> linked all over the place. I am also using GNU's ld and as. But still it
> fails. Not being a C programmer, I am also confused by the fact that a
> grep for "udivdi" in libgcc on Linux returns a match, whereas is fails on
> Solaris/Intel. So I am not even sure my libgcc.a contains the function.
> (Yes, I am grasping a bit here).
> 
> Has anyone else on the list run into a similar issue on Solaris/Intel? I
> would appreciate any suggestions (outside of basing the box and installing
> Linux [grin]).
> 
> -T
> 
> -- 
> Tarus Balog
> Consultant
> Sortova Consulting Group, http://www.sortova.com
> +1-919-696-7625
> tarus at sortova.com
> 
> 
> 
> _______________________________________________
> TriLUG mailing list
>     http://www.trilug.org/mailman/listinfo/trilug
> TriLUG Organizational FAQ:
>     http://www.trilug.org/~lovelace/faq/TriLUG-faq.html
-- 

  "Microsoft, where quality is job 1.1" -Anonymous





More information about the TriLUG mailing list