zoukankan      html  css  js  c++  java
  • BigEndian & LittleEndian

    大端模式Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

    小端模式Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

    小端模式 :强制转换数据不需要调整字节内容。

    大端模式 :符号位的判定固定为第一个字节,容易判断正负。

    采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。

    例:32bit宽的数0x12345678在Little-endian模式以及Big-endian模式在内存中的存放方式为(假设从地址0x4000开始存放):

    内存地址 Little-Endian Big-Endian
    0x4000 0x78 0x12
    0x4001 0x56 0x34
    0x4002 0x34 0x56
    0x4003 0x12 0x78

    一般操作系统都是小端,而通讯协议是大端的。

    常见CPU的字节序:

    Big Endian : PowerPC、IBM、Sun
    Little Endian : x86、DEC
    ARM既可以工作在大端模式,也可以工作在小端模式。

    常见文件的字节序:

    Adobe PS – Big Endian
    BMP – Little Endian
    DXF(AutoCAD) – Variable
    GIF – Little Endian
    JPEG – Big Endian
    MacPaint – Big Endian
    RTF – Little Endian

    另外,Java和所有的网络通讯协议都是使用Big-Endian的编码。

    判断字节序的小程序

    BOOL IsBigEndian()
    {
        int a = 0x1234;
        char b =  *(char *)&a;  //通过将int强制类型转换成char单字节,通过判断起始存储位置。即等于 取b等于a的低地址部分
        if( b == 0x12)
        {
            return TRUE;
        }
        return FALSE;
    }<span style="font-family: Arial, Verdana, sans-serif; white-space: normal; background-color: rgb(255, 255, 255); "> </span>

    联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写:

    BOOL IsBigEndian()
    {
        union NUM
        {
            int a;
            char b;
        }num;
        num.a = 0x1234;
        if( num.b == 0x12 )
        {
            return TRUE;
        }
        return FALSE;
    }

    从软件的角度理解端模式

    进行网络数据传递时,必须要考虑端模式的转换。x86的CPU使用的是LE(Windows中称为“主机字节序”),而SocksAddr中使用的则是BE(就是“网络字节序”),所以在使用网络编程时需要使用htns,htnl,nths,nthl来倒字节序。

    #define ntohs(n)     //16位数据类型网络字节顺序到主机字节顺序的转换
    #define htons(n)     //16位数据类型主机字节顺序到网络字节顺序的转换
    #define ntohl(n)     //32位数据类型网络字节顺序到主机字节顺序的转换
    #define htonl(n)     //32位数据类型主机字节顺序到网络字节顺序的转换

    其中互联网使用的网络字节顺序采用大端模式进行编址,而主机字节顺序根据处理器的不同而不同,如PowerPC处理器使用大端模式,而Pentuim处理器使用小端模式。
           大端模式处理器的字节序到网络字节序不需要转换,此时ntohs(n)=n,ntohl = n;而小端模式处理器的字节序到网络字节必须要进行转换,此时ntohs(n) = __swab16(n),ntohl = __swab32(n)。__swab16与__swab32函数定义如下所示。

    #define ___swab16(x)
    {
                __u16 __x = (x);
                ((__u16)(
                            (((__u16)(__x) & (__u16)0x00ffU) << 8) |
                            (((__u16)(__x) & (__u16)0xff00U) >> 8) ));
    }
    
    
    #define ___swab32(x)
    {
                __u32 __x = (x);
                ((__u32)(
                            (((__u32)(__x) & (__u32)0x000000ffUL) << 24) |
                            (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) |
                            (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) |
                            (((__u32)(__x) & (__u32)0xff000000UL) >> 24) ));
    }

    PowerPC处理器提供了lwbrx,lhbrx,stwbrx,sthbrx四条指令用于处理字节序的转换以优化__swab16和__swap32这类函数。此外PowerPC处理器中的rlwimi指令也可以用来实现__swab16和__swap32这类函数。

          在对普通文件进行处理也需要考虑端模式问题。在大端模式的处理器下对文件的32,16位读写操作所得到的结果与小端模式的处理器不同。单纯从软件的角度理解上远远不能真正理解大小端模式的区别。事实上,真正的理解大小端模式的区别,必须要从系统的角度,从指令集,寄存器和数据总线上深入理解,大小端模式的区别。

    从系统的角度理解端模式

    MSB:MoST Significant Bit ------- 最高有效位

    LSB:Least Significant Bit ------- 最低有效位

          处理器在硬件上由于端模式问题在设计中有所不同。从系统的角度上看,端模式问题对软件和硬件的设计带来了不同的影响,当一个处理器系统中大小端模式同时存在时,必须要对这些不同端模式的访问进行特殊的处理。
          PowerPC处理器主导网络市场,可以说绝大多数的通信设备都使用PowerPC处理器进行协议处理和其他控制信息的处理,这也可能也是在网络上的绝大多数协议都采用大端编址方式的原因。因此在有关网络协议的软件设计中,使用小端方式的处理器需要在软件中处理端模式的转变。而Pentium主导个人机市场,因此多数用于个人机的外设都采用小端模式,包括一些在网络设备中使用的PCI总线,Flash等设备,这也要求在硬件设计中注意端模式的转换。
          本文提到的小端外设是指这种外设中的寄存器以小端方式进行存储,如PCI设备的配置空间,NOR FLASH中的寄存器等等。对于有些设备,如DDR颗粒,没有以小端方式存储的寄存器,因此从逻辑上讲并不需要对端模式进行转换。在设计中,只需要将双方数据总线进行一一对应的互连,而不需要进行数据总线的转换。
          如果从实际应用的角度说,采用小端模式的处理器需要在软件中处理端模式的转换,因为采用小端模式的处理器在与小端外设互连时,不需要任何转换。而采用大端模式的处理器需要在硬件设计时处理端模式的转换。大端模式处理器需要在寄存器,指令集,数据总线及数据总线与小端外设的连接等等多个方面进行处理,以解决与小端外设连接时的端模式转换问题。在寄存器和数据总线的位序定义上,基于大小端模式的处理器有所不同。
          一个采用大端模式的32位处理器,如基于E500内核的MPC8541,将其寄存器的最高位msb(most significant bit)定义为0,最低位lsb(lease significant bit)定义为31;而小端模式的32位处理器,将其寄存器的最高位定义为31,低位地址定义为0。与此向对应,采用大端模式的32位处理器数据总线的最高位为0,最高位为31;采用小端模式的32位处理器的数据总线的最高位为31,最低位为0。         
          大小端模式处理器外部总线的位序也遵循着同样的规律,根据所采用的数据总线是32位,16位和8位,大小端处理器外部总线的位序有所不同。大端模式下32位数据总线的msb是第0位,MSB是数据总线的第0~7的字段;而lsb是第31位,LSB是第24~31字段。小端模式下32位总线的msb是第31位,MSB是数据总线的第31~24位,lsb是第0位,LSB是7~0字段。大端模式下16位数据总线的msb是第0位,MSB是数据总线的第0~7的字段;而lsb是第15位,LSB是第8~15字段。小端模式下16位总线的msb是第15位,MSB是数据总线的第15~7位,lsb是第0位,LSB是7~0字段。大端模式下8位数据总线的msb是第0位,MSB是数据总线的第0~7的字段;而lsb是第7位,LSB是第0~7字段。小端模式下8位总线的msb是第7位,MSB是数据总线的第7~0位,lsb是第0位,LSB是7~0字段。
          由上分析,我们可以得知对于8位,16位和32位宽度的数据总线,采用大端模式时数据总线的msb和MSB的位置都不会发生变化,而采用小端模式时数据总线的lsb和LSB位置也不会发生变化。
          为此,大端模式的处理器对8位,16位和32位的内存访问(包括外设的访问)一般都包含第0~7字段,即MSB。小端模式的处理器对8位,16位和32位的内存访问都包含第7~0位,小端方式的第7~0字段,即LSB。由于大小端处理器的数据总线其8位,16位和32位宽度的数据总线的定义不同,因此需要分别进行讨论在系统级别上如何处理端模式转换。在一个大端处理器系统中,需要处理大端处理器对小端外设的访问。

    全文整理自:

    详解大端模式和小端模式

    深入浅出大端和小端

  • 相关阅读:
    Software Solutions CACHE COHERENCE AND THE MESI PROTOCOL
    CACHE COHERENCE AND THE MESI PROTOCOL
    Multiprocessor Operating System Design Considerations SYMMETRIC MULTIPROCESSORS
    Organization SYMMETRIC MULTIPROCESSORS
    PARALLEL PROCESSING
    1分钟内发送差评邮件
    Secure Digital
    SYMMETRIC MULTIPROCESSORS
    A Taxonomy of Parallel Processor Architectures
    parallelism
  • 原文地址:https://www.cnblogs.com/pure/p/3034066.html
Copyright © 2011-2022 走看看