大端 vs 小端 —— 基础原理
最近有人问王师傅一个问题:车内通信如果涉及到 CAN 报文和以太网报文转换的场景,大端、小端,或者 Intel、Motorola 格式会对数据转换造成什么影响吗?相信大家都曾学习或者了解过什么是大端、小端,可总是过眼云烟,扭头就忘。今天,希望能通过几个简单的例子帮助大家对这块的内容有个更好的理解。内部比较多,会分三篇文章,分别从基础原理、网络字节序和 Intel & Motorola 格式三个部分来做介绍。
关键字:大端、小端、网络字节序、Intel、Motorola、车载以太网、CAN
Q&A什么是大端和小端?
大端(Big-endian) 和 小端(Little-endian) 指的是字节的顺序 (Byte Order),当数据在存储的时候,是最高有效字节 (Most Significant byte:MSB) 先存储还是最低有效字节 (Least Significant Byte:LSB) 先存储。
最高有效字节 (MSB): 最大权重的字节,发生改变对数值影响最大。
最低有效字节 (LSB): 最小权重的字节,发生改变对数值影响最小。
举个例子
十六进制数字0x142857, 该数字的 MSB 为0x14,LSB 为0x57。
如果 MSB 减1,变成0x132857,数值会减少65535,数值改变较大——权重较大。
如果 LSB 减1,变成0x142856,数值仅减少1,数值改变较小——权重较小。
再举个例子
假如你有20001块钱,如果2变成了1,20001会变成10001,直接损失10000块;但如果1变成了0,20001会变成20000,仅损失1块,所以最左侧的2最重要 (Most Significant),最右侧的1最不重要 (Least Significant)。
除了字节,比特 (位) 也有最高有效位 (Most Significant Bit,这里为了和字节的 MSB 做区分,在本文中将其表示为 MSBit) 和最低有效位 (Least Significant Bit:LSBit)。
比如 0 b 1 010011 0 ,红色1为 MSBit,绿色0为 LSBit。
在数据存储时,每个存储单元都有一个自己的地址 (比如16位机器的地址范围是0x0000 ~ 0xFFFF) ,每个地址存储1个字节的数据。如果我们想存储 0x14285700,存储地址为 0x1001 至 0x1004,大端小端的处理如下:
大端模式: 最高有效字节先存储,即数据的最高有效字节 (MSB) 保存在内存的低地址中,而数据的最低有效字节 (LSB) 保存在内存的高地址中 (和我们的阅读顺序一致) 。
小端模式: 最低有效字节先存储,即数据的低字节 (LSB) 保存在内存的低地址中,数据的高字节 (MSB) 保存在内存的高地址中。
另外,除了字节序,在每一个字节中,比特位也有自己的顺序,叫比特序或者位序 (Bit Order) 。下图为二进制数字 0b10100110 (166) 在大小端中的表示:
大端 ,左侧为最高有效位 MSBit,右侧为最低有效位 LSBit。
小端 ,左侧为最低有效位 LSBit,右侧为最高有效位 MSBit。
在系统中,位序通常和字节序一致,内存的读写是从低地址开始,数据的收发也是一样,所以大端更符合人类的阅读顺序和习惯。
大端、小端的由来
大端、小端,这两个名词是1980年,由 Danny Cohen 在他的文章《On Holy Wars and a Plea for Peace》中引入到计算器领域的(这篇文章在网上可以搜到,大家有兴趣可以去看看,其中主要阐述了大小端的问题)。
最初的出处,是1726年出版的长篇小说《Gulliver’s Travels》,作者是 Jonathan Swift,小说中两个小人国 Blefuscu 和 Lilliput 之间因为鸡蛋应该从哪端打破而爆发了冲突,支持从大端(big end)打鸡蛋的人被称为 Big Endians,支持从小端(little end)打鸡蛋的人被称为 Little Endians。这是一篇讽刺小说,其中讽刺了很多毫无意义的党派斗争。
Danny Cohen 之所以引用这两个名词,除了比较形象之外,可能是因为当时计算机具体应该使用大端还是小端在业内引起了不小的争论,他认为这些争论没有意义,就如他在文章结尾处说的:
It is more important to agree upon an order than which order is agreed upon. How about tossing a coin ?
《On Holy Wars and a Plea for Peace》
今天就先分享这么多,这里介绍了大端和小端的基础知识。那么车内通信的时候是使用大端还是小端?Intel 和 Motorola 格式和大小端又有什么关系呢?敬请期待接下来的文章。
封面图片作者 Oliver Widder
图片来源 https://geek-and-poke.com
彩蛋
文中举例时提到了一个数字 142857
这个数字是十进制循环数
有人称它为走马灯数
大家有兴趣可以试着算一算
将这个数字分别乘以1到7
看看得到什么数字
142857 | 285714 | 428571
571428 | 714285 | 857142
999999
谢谢分享