• 大端和小端(ZZ)


    Byte Endian是指字节在内存中的组织,所以也称它为Byte Ordering,或Byte Order。
    对于数据中跨越多个字节的对象, 我们必须为它建立这样的约定:
    (1) 它的地址是多少?
    (2) 它的字节在内存中是如何组织的?
    针 对第一个问题,有这样的解释: 对于跨越多个字节的对象,一般它所占的字节都是连续的,它的地址等于它所占字节最低地址。(链表可能是个例外,但链表的地址可看作链表头的地址)。比如: int x, 它的地址为0x100。 那么它占据了内存中的0x100, 0x101, 0x102, 0x103这四个字节(32位系统,所以int占用4个字节)。
    上面只是内存字节组织的一种情况: 多字节对象在内存中的组织有一般有两种约定。 考虑一个W位的整数:它的各位表达如下[Xw-1, Xw-2, ... , X1, X0],它的:
        MSB (Most Significant Byte, 最高有效字节)为 [Xw-1, Xw-2, ... Xw-8]
        LSB (Least Significant Byte, 最低有效字节)为 [X7,X6,..., X0]
        其余的字节位于MSB, LSB之间。 LSB和MSB谁位于内存的最低地址, 即谁代表该对象的地址? 这就引出了大端(Big Endian)与小端(Little Endian)的问题。
    如果LSB在MSB前面, 既LSB是低地址, 则该机器是小端; 反之则是大端。
    下文举例说明在计算机中大小端模式的区别。

    如果将一个32位的整数0x12345678存放到一个整型变量(int)中, 这个整型变量采用大端或者小端模式在内存中的存储由下表所示。为简单起见,这里使用OP0表示一个32位数据的最高字节MSB,使用OP3表示一个32位数据最低字节LSB。

    地址偏移

    大端模式

    小端模式

    0x00

    12(OP0)

    78(OP3)

    0x01

    34(OP1)

    56(OP2)

    0x02

    56(OP2)

    34(OP1)

    0x03

    78(OP3)

    12(OP0)

    即:

    Big Endian

       低地址                                            高地址
       ----------------------------------------->
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |     12     |      34    |     56      |     78    |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    Little Endian

       低地址                                            高地址
       ----------------------------------------->
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |     78     |      56    |     34      |     12    |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



    如果将一个16位的整数0x1234存放到一个短整型变量(short)中。这个短整型变量在内存中的存储在大小端模式由下表所示。

    地址偏移

    大端模式

    小端模式

    0x00

    12(OP0)

    34(OP1)

    0x01

    34(OP1)

    12(OP0)

    由上表所知,采用大小端模式对数据进行存放的主要区别在于在存放的字节顺序,big endian是指低地址存放最高有效字节(MSB),而little endian则是低地址存放最低有效字节(LSB)。采用大端方式进行数据存放比较直观,而采用小端方式进行数据存放利于计算机处理。到目前为止,采用大端或者小端进行数据存放,其孰优孰劣也没有定论。(小端是低位先存,大端高位先存)

    有的处理器系统采用了小端方式进行数据存放,如Intel的奔腾。有的处理器系统采用了大端方式进行数据存放,如IBM半导体和Freescale的PowerPC处理器。不仅对于处理器,一些外设的设计中也存在着使用大端或者小端进行数据存放的选择。

    因此在一个处理器系统中,有可能存在大端和小端模式同时存在的现象。这一现象为系统的软硬件设计带来了不小的麻烦,这要求系统设计工程师,必须深入理解大端和小端模式的差别。大端与小端模式的差别体现在一个处理器的寄存器,指令集,系统总线等各个层次中。



    判断大端小端

        int i=1;  
        char *p=(char *)&i;  
        if(*p==1)    
               printf("Little-Endian"); 
        else
               printf("Big-Endian");

          如果小端方式,则i所分配的内存最小地址那个字节中就存着1,其他字节是0(00000001),大端的话则1在i的最高地址字节处存放。char是一个 字节,所以强制将char型量p指向i,则p指向的一定是i的最低地址,那么就可以判断p中的值是不是1来确定是不是小端。



    请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1

    int checkCPU( )

    {

        {

               union w

               {  

                      int a;

                      char b;

               } c;

               c.a = 1;

               return(c.b ==1);

             

        }

    }

    嵌入式系统开发者应该对Little-endian和Big-endian 模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。
    例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

    内存地址

    0x4000

    0x4001

    存放内容

    0x34

    0x12


    而在Big-endian模式CPU内存中的存放方式则为:

    内存地址

    0x4000

    0x4001

    存放内容

    0x12

    0x34


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

    内存地址

    0x4000

    0x4001

    0x4002

    0x4003

    存放内容

    0x78

    0x56

    0x34

    0x12


    而在Big-endian模式CPU内存中的存放方式则为:

    内存地址

    0x4000

    0x4001

    0x4002

    0x4003

    存放内容

    0x12

    0x34

    0x56

    0x78


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

    那么CPU存储一个字节的数据时其字节内的8个比特之间的顺序是否也有 big endian和little endian之分?或者说是否有比特序的不同? 实际上,这个比特序是同样存在的。下面以数字0xB4(10110100)用图加以说明。

    Big Endian

       msb                                                         lsb
       ---------------------------------------------->
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |   1  |   0  |   1  |   1  |   0  |   1  |   0  |   0  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    Little Endian

       lsb                                                         msb
       ---------------------------------------------->
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |   0  |   0  |   1  |   0  |   1  |   1  |   0  |   1  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


         实际上,由于CPU存储数据操作的最小单位是一个字节,其内部的比特序是什么样对我们的程序来说是一个黑盒子。也就是说,你给我一个指向0xB4这个数的 指针,对于big endian方式的CPU来说,它是从左往右依次读取这个数的8个比特;而对于little endian方式的CPU来说,则正好相反,是从右往左依次读取这个数的8个比特。而我们的程序通过这个指针访问后得到的数就是0xB4,字节内部的比特 序对于程序来说是不可见的,其实这点对于单机上的字节序来说也是一样的。

  • 相关阅读:
    为什么linux有足够的内存还进行swap?
    vmstat命令的使用
    Windows远程服务器不能复制粘贴
    Windows可以ping通百度,但是用浏览器打不开网页
    java形式参数分别是基本类型和引用类型的调用
    Ubuntu16.04安装Python3.6 和pip
    Python2/3共存,pip2/3共存
    multiprocessing模块
    Python-进程与线程
    鼠标不能动,插上了但没反应
  • 原文地址:https://www.cnblogs.com/lihaozy/p/2816219.html
Copyright © 2020-2023  润新知