《操作系统真象还原》——0.19 什么是大端字节序、小端字节序

简介: 字节序不仅是在CPU访问内存中的概念,而且也包括在文件存储和网络传输中。bmp格式的图片就属于小端字节序,而jpeg格式的图片则为大端字节序,这没什么可说的,采用什么序列完全是开发者设计产品时的需要。

本节书摘来自异步社区《操作系统真象还原》一书中的第0章,第0.19节,作者:郑钢著,更多章节内容可以访问云栖社区“异步社区”公众号查看

0.19 什么是大端字节序、小端字节序

先说一下为什么会产生字节序的问题。

内存是以字节为单位读写的,其最小的读写单位就是字节。故如果在内存中只写入一个字节,一个内存的存储单元便可将其容纳了,只要访问这一内存地址就能够完整取出这1字节。可是1字节要能够表示的范围只有0~255(先只考虑无符号数),超过这个范围的数,只好用多个字节连在一起来表示。因此,在我们的32位程序中,定义的数据类型很多。1字节的数据类型只有char型,像int型要占4字节,double型要占用8字节。正如解决了一个问题又抛出了新的问题一样,解决了数值范围的问题,那带来的新的问题是这么多个字节该以怎样的顺序排放呢。一个超过255的数字必然要占用2个字节以上,这两个字节,在物理内存中,哪个在前?哪个在后?拿0x1234举例,数值中的高位12是放在内存的高地址处,还是低地址处?

于是就产生了这两种相反的排列顺序。

(1)小端字节序是数值的低字节放在内存的低地址处,数值的高字节放在内存的高地址。

(2)大端字节序是数值的低字节放在内存的高地址处,数值的高字节放在内存的低地址。

为了让大家理解得更直观,我在虚拟机bochs中操作一下,咱们看一下真正的0x12345678在内存中是怎样存储的,如图0-9所示。

上面的b 0x7c00是我在内存的0x7c00处插入了一个断点,其实这与要说明的问题无关,怕有同学好奇就稍带说一句,因为0x7c00是BIOS把mbr加载到内存后会跳转过去的地址,所以在此处能停下来。咱们只要关注xp/4 0x200000,这是显示以物理内存0x200000开始处的4个字节,可见其为00、00、00、00,地址是从左到右逐渐升高的,其中每一对00就占用1个字节,它们的值都是0。现在用setpmem命令在该地址处写入0x12345678后,再用xp/4命令查看内存地址0x200000处的内容,可见已经不是4个00了,由内存的低地址到高地址,依次变成了0x78、0x56、0x34、0x12。这说明bochs模拟的x86体系结构虚拟机是小端字节序,即数值上的低字节0x78在物理内存上的低地址,其他数值也依次符合小端字节序。

选择哪种字节序,这是硬件厂商考虑的问题,对于这种二选一的选择,选择了一方的时候,就必然丢了另一方。

看看这两种字节序的优势。

(1)小端:因为低位在低字节,强制转换数据型时不需要再调整字节了。

(2)大端:有符号数,其字节最高位不仅表示数值本身,还起到了符号的作用。符号位固定为第一字节,也就是最高位占据最低地址,符号直接可以取出来,容易判断正负。

简要说明一下小端的优势。因为在做强制数据类型转换时,如果转换是由低精度转向高精度,这数值本身没什么变化,如short 是2字节,将其转换为4字节的int类型,无非是由0x1234变成了0x00001234,数值上是不变的,只是存储形式上变了。如果转换是高精度转向低精度,也就是多个字节的数值要减少一些存储字节,这必然是要丢弃一部分数值。编译器的转换原则是强制转换到低精度类型,丢弃数值的高字节位,只保留数值的低字节,如图0-10所示。

screenshot

由图0-10上输出可见,0x12345678由4字节的int型强制转向了2字节的short型后,只保留了低字节的0x5678。

对于大端的优势,就硬件而言,就是符号位的判断变得方便了。最高位在最低地址,也就是直接就可以取到了,不用再跨越几个字节,减少了时钟周期。另外,对于人类来说,还是大端看上去顺眼,毕竟咱们存储0x12345678到内存时,它在内存中的存储顺序也是0x12345678,而不是0x78563412,这样看上去才直观。

常见CPU的字节序如下。

(1)大端字节序:IBM、Sun、PowerPC。

(2)小端字节序:x86、DEC。

ARM体系的CPU则大小端字节序通吃,具体用哪类字节序由硬件选择。

字节序不仅是在CPU访问内存中的概念,而且也包括在文件存储和网络传输中。bmp格式的图片就属于小端字节序,而jpeg格式的图片则为大端字节序,这没什么可说的,采用什么序列完全是开发者设计产品时的需要。

网络字节序就是大端字节序,所以在x86架构上的程序在发送网络数据时,要转换字节顺序。

关于字节序就介绍到这里,读者若觉得意犹未尽可以自行查阅。

相关文章
|
存储 小程序 Unix
《操作系统真象还原》——0.28 MBR、EBR、DBR和OBR各是什么
MBR和EBR是分区工具创建维护的,不属于操作系统管理的范围,因此操作系统不可以往里面写东西,注意这里所说的是“不可以”,其实操作系统是有能力读写任何地址的,只是如果这样做的话会破坏“系统控制权接力赛”所使用的数据,下次开机后就无法启动了。
3470 0
|
Linux C语言
《操作系统真象还原》——导读
以上情况对我们学习操作系统来说也同样存在,比如当老师介绍中断发生时的上下文保护时,我们更多的疑问不是如何保存CPU的上下文数据,而是想知道为什么在不同的特权级下会使用不同的栈,这背后的原理是什么,并且这是如何做到的。
1615 0
|
JavaScript 前端开发 Linux
《操作系统真象还原》——2.3 让MBR先飞一会儿
虽说主引导记录mbr是咱们能够掌控的第一个程序,但这并不是让我们为之激动的理由。我们平时所写的程序都要依赖于操作系统,而我们即将实现的这个程序是独立于操作系统的,能够直接在裸机上运行,这才是让我们激动的理由,对咱们来说这无疑是历史性的一刻。
2360 0
|
存储 内存技术 程序员
《操作系统真象还原》——2.2 软件接力第一棒,BIOS
Intel 8086有20条地址线,故其可以访问1MB的内存空间,即2的20次方=1048576=1MB,地址范围若按十六进制来表示,是0x00000到0xFFFFF。不知道硬件工程师当时设计的初衷是什么,总之人家有自己的理由,这1MB的内存空间被分成多个部分。
2035 0
|
存储
《操作系统真象还原》——第2章 编写MBR主引导记录,让我们开始 掌权 2.1 计算机的启动过程
所以,都在内存中运行程序,操作系统和硬件设计都省事了,这可能也是为了方式的统一吧,否则总不能出现某种存储介质后,操作系统和硬件就要付出额外努力去支持。当然,具体原因只有硬件工程师才知道,咱们在此先打住,继续咱们的内容。
1505 0
|
运维 Linux
《操作系统真象还原》——1.5 运行bochs
我们键入的是上面长方形框框中的部分:bochsrc.disk。由于我们刚刚把此文件放到了bochs的安装路径下,bochs找到了它并加载成功。紧接着下面给出的默认选项变成了[6],也就是Begin simulation选项,开始模拟x86硬件平台。
4170 0
|
NoSQL
《操作系统真象还原》——1.4 配置bochs
Bochs既然是模拟硬件的,它就得知道,您需要它模拟的计算机是什么样的,换句话说,在这个虚拟机中有哪些硬件,启动顺序是什么,是从软盘开始,还是从硬盘开始?人家也得像模像样地跟BIOS差不多才行。
2650 0
|
NoSQL Linux iOS开发
《操作系统真象还原》——1.3 操作系统的宿主环境
虚拟机在当今已经不是陌生的概念了,要是在几年前,我还得搬出个概念放在这给大家看看。个人觉得,要解释一个东西是什么,不如直接解释这个东西解决了哪些问题,这样大家自然就从本质上真正理解了它是什么。
2628 0
|
Linux C语言 编译器
《操作系统真象还原》——1.2 我们需要哪些编译器
GCC是由理查德·马修·斯托曼在1985年开始的。他首先扩展一个旧有的编译器,使它能编译C,这个编译器一开始是以Pastel语言所写的。Pastel是一个不可移植的Pascal语言特殊版,这个编译器也只能编译Pastel语言。
1798 0
|
编译器 C语言
《操作系统真象还原》——第1章 部署工作环境 1.1工欲善其事,必先利其器
软件是由编程语言来实现的,即使是编译器本身,它的开发人员都不愿意用底层语言去构建(GCC是用C语言完成的),只有到万不得已的时候才会用汇编语言来写。我们也是一样,能用省事的方法就不要自找麻烦,如果某位大神能直接写机器码,小弟真心恳求与您见上一面,希望您收我为徒,我要当面磕头拜师
1753 0