查看原文
其他

什么是大小端模式?

来源:百度百科及https://www.cnblogs.com/Alandre/p/4878841.html


一、什么是大小端模式?

大端模式(Big-Endian),是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。 

小端模式(Little-Endian),是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。

二、名字由来

在乔纳森·斯威夫特的著名讽刺小说《格列夫游记》中,小人国内部分裂成Big-endian和Little-endian两派,区别在于一派要求从鸡蛋的大头把鸡蛋打破,另一派要求从鸡蛋的小头把鸡蛋打破。斯威夫特借以讽刺英国的政党之争,在计算机工业中指数据储存顺序的分歧。

三、简易区分

下面以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value。

Big-Endian: 低地址存放高位,如下:

  1. 高地址

  2.   ---------------

  3.   buf[3] (0x78) -- 低位

  4.   buf[2] (0x56)

  5.   buf[1] (0x34)

  6.   buf[0] (0x12) -- 高位

  7.   ---------------

  8. 低地址

Little-Endian: 低地址存放低位,如下:

  1. 高地址

  2.   ---------------

  3.   buf[3] (0x12) -- 高位

  4.   buf[2] (0x34)

  5.   buf[1] (0x56)

  6.   buf[0] (0x78) -- 低位

  7.   --------------

  8. 低地址


内存地址小端模式存放内容大端模式存放内容
0x40000x780x12
0x40010x560x34
0x40020x340x56
0x40030x120x78

四、为什么会有大小端模式之分呢?

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。

因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于 大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。

我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以随时在程序中(在ARM Cortex 系列使用REV、REV16、REVSH指令 )进行大小端的切换。

五、判断处理器是大端模式还是小端模式?

1、因特尔i3-3110M处理器

  1. /*******************************************************************************************************

  2. ** 判断大小端

  3. ********************************************************************************************************/

  4. #include <stdio.h>


  5. // 主函数

  6. int main(void)

  7. {

  8. int a = 0x12345678;

  9. char *cp = (char*)&a;

  10. if (*cp == 0x78)

  11. {

  12. printf("little endian\n"); //运行结果

  13. }

  14. else

  15. {

  16. printf("big endian\n");

  17. }


  18. return 0;

  19. }

运行结果为:  即因特尔i3-3110M处理器为小端存储模式。

2、STM32F407

  1. #include "stm32f4xx.h"


  2. int main(void)

  3. {

  4. int u = 367328153; // 原始数据15 E4 FB 99

  5. int* k = &u;

  6. return 0;

  7. }

编译连接然后下载到开发板上,然后启动调试,通过监视窗口可以看到u的地址,然后在内存窗口可以看到字节序是反序的,所以说明STM32F407是小端的。据某些资料说ARM内核是可以设置大小端的,但是STM32是外设自动进入了小端,似乎是无法调整的。 

3、89C52

最后来一个大端的例子。手头上没有51的开发板,所以用的是软件仿真。

  1. #include <reg52.h>


  2. int main()

  3. {

  4. int longbit = sizeof(long);


  5. long u = 367328153; // 原始数据15 E4 FB 99

  6. long* k = &u;


  7. return 0;

  8. }

结果:

六、应用场景

1、不同端模式的处理器进行数据传递时必须要考虑端模式的不同。

2、在网络上传输数据时,由于数据传输的两端对应不同的硬件平台,采用的存储字节顺序可能不一致。所以在TCP/IP协议规定了在网络上必须采用网络字节顺序,也就是大端模式。对于char型数据只占一个字节,无所谓大端和小端。而对于非char类型数据,必须在数据发送到网络上之前将其转换成大端模式。接收网络数据时按符合接受主机的环境接收。

七、现阶段状况

目前Intel的80x86系列芯片是唯一还在坚持使用小端的芯片,ARM芯片默认采用小端,但可以切换为大端;而MIPS等芯片要么采用全部大端的方式储存,要么提供选项支持大端——可以在大小端之间切换。

另外,对于大小端的处理也和编译器的实现有关,在C语言中,默认是小端(但在一些对于单片机的实现中却是基于大端,比如Keil 51C),Java是平台无关的,默认是大端。在网络上传输数据普遍采用的都是大端。




转发、点在看就是对小编最大的支持!


猜你喜欢

编写优质嵌入式C程序(一)

编写优质嵌入式C程序(二)

【Linux笔记】文本文件查看命令

【Linux笔记】文件的权限

分享一个很酷的技巧

【Git笔记】分布式版本控制系统

嵌入式软件工程师经典面试题(一)



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存