关于字节序和比特序 Little Endian Big Endian

 


 

不同CPU存取顺序不同,PowerPC系列采用Big Endian(BE)方式存储,而x86系列则采用Little Endian(LE)方式。

 

 

对于0x12345678LE架构CPU存取

 

LE架构CPU存取:

 


 

BE架构CPU存取:

 


注:在LE系统中,通过htonlhtons仅转换字节序,每个字节中的比特序没有变化,读取还是从高到低,如下:

 

 

 




 

应用举例

 

1. IPv4地址

如下192.168.10.1LE系统中通过inet_addr(“192.168.10.1”)作为整数为:0x10aa8c0

 

 

 

2. IPv6地址

2013:4::119在内存中作为128位整数如下:

通过:inet_pton(AF_INET6,saddr6, &addr6)转换后的

 

 

 

 

3. LE系统检查IP地址比特位是否置位,如128位的IPV6地址:

 

逻辑IPV6地址128位:

 

LE系统中按LE格式存储16字节如下:


 

LE系统中按BE格式存储16字节如下:

 

 


 

Linux内核对IP地址测试比特位函数addr_bit_set实现如下:

/*

 *      testbit

 */

#ifdefined(__LITTLE_ENDIAN)

# defineBITOP_BE32_SWIZZLE         (0x1F & ~7)

#else

# defineBITOP_BE32_SWIZZLE         0

#endif

 

static__inline__ __be32 addr_bit_set(void*token, intfn_bit)

{

         __be32*addr = token;

         /*

          * Here,

              1<< ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)

          * is optimized version of

          *      htonl(1<< ((~fn_bit)&0x1F))

          * See include/asm-generic/bitops/le.h.

          */

         return(__force __be32)(1 << ((~fn_bit ^BITOP_BE32_SWIZZLE) & 0x1f)) &

                addr[fn_bit >> 5];

}

 

注释中说明了关于掩码位的计算,下面更进一步解释一下

 

令:

M1 = 1 << ((~fn_bit ^BITOP_BE32_SWIZZLE) & 0x1f);

M2 = htonl(1<<((~fn_bit)&0x1F));

 

M1M2等价原因:

 

4字节为例,BELE比特序也是倒过来的,测试IP地址第0位,相当于测试BE格式的第31位,即有:~fn_bit &0x1f,等价于31-fn_bit。测试IP地址第31位,相当于测试BE格式的第0位,即时~fn_big&0xlf,等价于31-fn_bit1<<((~fn_bit)&0x1F)这个是LE32位掩码,所以转成BE格式掩码,即htonl(1<<((~fn_bit)&0x1F))

 

htonl就是把字节03对调,字节12对调。所以~fn_bit ^BITOP_BE32_SWIZZLE(~fn_bit)3位不变,高2位按位取反,即与BITOP_BE32_SWIZZLE=11000B即可实现。

 

注:异或运算,与1异或相当取反,与0异或保持不变。

 

 

下面举列来说明一下:

如:对0BE格式的IP测试,即fn_bit=0,参上图我们可以看出,BE格式的掩码应该是:

 

即在LE系统中为0x80,存储如下:

 

 

 


 

 

 

 

 

为什么在IP协议中,LE系统不把比特序转换BE后给网卡?

LE系统网卡本身有这样转换功能,网卡把数据按比特发到网络上时,每一字节是从高比特位开始读取,这样产生的就是BE格式的比特序列。

 

http://blog.csdn.net/lovekatherine/article/details/1564731

 

 


posted @ 2013-04-12 16:45  mull  阅读(819)  评论(0编辑  收藏  举报