note18-大端与小端–关于Endian的话题

big endian与little endian
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1871715
一、基础知识
1、位(bit)

来自英文bit,音译为“比特”,表示二进制位。位是计算机内部数据储存的最小单位,11010100是一个8位二进制数。一个二进制位只可以表示0和1两种状态(21);两个二进制位可以表示00、01、10、11四种(22)状态;三位二进制数可表示八种状态(23)……。

2、字节(byte)

字节来自英文Byte,音译为“拜特”,习惯上用大写的“B”表示。

字节是计算机中数据处理的基本单位。计算机中以字节为单位存储和解释信息,规定一个字节由八个二进制位构成,即1个字节等于8个比特(1Byte=8bit)。八位二进制数最小为00000000,最大为11111111;通常1个字节可以存入一个ASCII码,2个字节可以存放一个汉字国标码。

3、字

计算机进行数据处理时,一次存取、加工和传送的数据长度称为字(word)。一个字通常由一个或多个(一般是字节的整数位)字节构成。例如286微机的字由2个字节组成,它的字长为16;486微机的字由4个字节组成,它的字长为32位机。

计算机的字长决定了其CPU一次操作处理实际位数的多少,由此可见计算机的字长越大,其性能越优越。

另一种说法:



在计算机中,一串数码作为一个整体来处理或运算的,称为一个计算机字,简称宇。字通常分为若干个字节(每个字节一般是8位)。在存储器中,通常每个单元存储一个字,因此每个字都是可以寻址的。字的长度用位数来表示。

在计算机的运算器、控制器中,通常都是以字为单位进行传送的。宇出现在不问的地址其含义是不相同。例如,送往控制器去的字是指令,而送往运算器去的字就是一个数。

在计算机中作为一个整体被存取、传送、处理的二进制数字符串叫做一个字或单元,每个字中二进制位数的长度,称为字长。一个字由若干个字节组成,不同的计算机系统的字长是不同的,常见的有8位、16位、32位、64位等,字长越长,计算机一次处理的信息位就越多,精度就越高,字长是计算机性能的一个重要指标。目前主流微机都是32位机。

注意字与字长的区别,字是单位,而字长是指标,指标需要用单位去衡量。正象生活中重量与公斤的关系,公斤是单位,重量是指标,重量需要用公斤加以衡量。

字长

计算机的每个字所包含的位数称为字长。根据计算机的不同,字长有固定的和可变的两种。固定字长,即字长度不论什么情况都是固定不变的;可变字长,则在一定范围内,其长度是可变的。

字块

在信息处理中,一群字作为一个单元来处理的称为“字块”.也称“字组”。例如,储存于滋鼓的一个磁道上的字群就称为一个字块。在磁带上通常每120个字符就间隔一个字块际志,也称为一个字块。块与块之间一般留1.27―2.54厘米(1/2一1英寸)的间隔。在大容量存储中,信息都是以字块为单位而存入的,因此只有字块才是可选址的。目前,在高速绥冲技术中也引入了“字块”的概念。

二、计算机的CPU
机器字长是指该计算机能进行多少位二进制数的并行运算,实际上是指该计算机中的运算器有多少位,通常计算机的数据总线和寄存器的位数与机器字长一致。如某机器字长16位,表示该机器中,每次能完成两个16位二进制数的运算。由于参加运算的操作数和运算结果既可存放在处理器内部的寄存器中,也可存放在主存储器中。因此,机器字长既是运算器的长度,也是寄存器的长度,一般情况下,它也是存储器的字长。通常,机器字长越长,计算机的运算能力越强,其运算精度也越高。


衡量机器字长的单位可用“位(bit)”,位是计算机内最小的信息单位,8位构成一个“字节(byte)”,现代计算机的机器字长一般都是8位的整数倍,如8位、16位、32位、64位和128位等,即字长由2个字节、4个字节、8个字节或16个字节组成,所以也可用“字节”来表示机器字长。


微型计算机的几个主要性能指标

(1)主频:CPU(微处理器)的时钟工作频率。例如:CPU PIV 主频3.0G以上

(2)运算速度:衡量CPU工作快慢的指标,(每秒完成多少次运算),可达每秒几十万亿次。 IBM最新生产的欧洲最快的超级计算机(名为“MareNostrum”)每秒钟可以运算40万亿次。

(3)字长:CPU一次可以处理的二进制位数,字长主要影响计算机的精度和速度,字长越长,计算机处理数据的速度越快,计算精度越高。

“32位微型计算机”:计算机机器字长为32位。

字长16位的计算机:表示在计算机内部,数以16位二进制数表示。

不同的芯片有不同的字长, 目前芯片有多种型号,其中奔腾Ⅳ(PIV)芯片的字长是:64位

(4)cache: 高速缓冲存储器。缓存大小也是CPU的重要指标之一,缓存容量的增大,可以大幅度提升CPU内部读取数据的命中率。

(5)主存容量(内存容量):衡量计算机记忆能力的指标,内存越大,机器的运行速度就越快

(6)输入输出数据传输速率:与外设交换数据的速度。如与硬盘交换数据的速率、打印机的输出速率等。

衡量微型计算机价值的主要依据是: 性能价格比

三、字节顺序
谈到字节序的问题,必然牵涉到两大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。那么究竟什么是big endian,什么又是little endian呢?


这里的endian指的是当物理上的最小单元(byte)比逻辑上的最小单元(比如word或一个多字节数据)小时,逻辑到物理的单元排布关系。当前的存储器,多以byte为访问的最小物理单元,在通信领域中,这里往往是bit(位),不过原理也是类似的。


当一个逻辑上的单元必须分割为物理上的若干单元时就存在了先放谁后放谁的问题,于是endian的问题应运而生了,对于不同的存储方法,就有Big-endian和Little-endian两个描述。


因此,这里的endian是针对逻辑最小单元内部的字节顺序而言。这个逻辑最小单元可以是一个字,也可以是一个单独的多字节数据。由于机器字长是固定的,而数据类型不同,其字节数也不同。当数据长度小于或等于机器字长时,整个数据可以存放在同一个word内存空间中,数据的字节序就是该word的字节序;但是,当该数据长度大于机器字长时,word内部字节序好理解,问题是被word分割开的各部分间顺序怎么分布?从理论上讲,endian不单局限于word内部,对于逻辑最小单元内部被字分割开的各部分也适用。但不同的硬件平台,也有例外,如ARM。这里只考虑一般情况。


假设机器上Word的长度是16或32位,一个Byte的长度是8位。如果一个数超过一个Word的长度,必须先按Word分成若干部分,然后每一部分(即每个Word内部)按Big-Endian或者Little-Endian的不同操作来处理字节。


一个例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12

上面的数长度为32位,若字长为32位,上面分布很好理解,若字长为16位时,也是如此分布。同理,对64位数,在little endian内存模式下,其低32位保存在低地址的字单元中,高32为保存在高地址的字单元中;在big endian模式下,其低32位保存在高地址的字单元中,高32位保存在低地址的字单元中。


此外,假定有一数据区域中包含N个数据,这个数据区域显然不是逻辑上的最小单元,而其中具体的每个数据才是逻辑最小单元,只有逻辑最小单元内部字节顺序才涉及到endian问题,而N个数据之间的顺序则与此无关。


字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端(little endian)、大端(big endian)两种字节顺序。小端字节序指低位字节数据存放在内存低地址处,高位字节数据存放在内存高地址处;大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处。


即big endian:最高位字节在地址最低位,最低位字节在地址最高位,依次排列。一个Word中的高位的Byte放在内存中这个Word区域的低地址处。


little endian:最低字节在最低位,最高字节在最高位,反序排列。一个Word中的低位的Byte放在内存中这个Word区域的低地址处。


Big endian machine: It thinks the first byte it reads is the biggest.
Little endian machine: It thinks the first byte it reads is the littlest.
其实big endian是指低地址存放最高有效字节(MSB),而little endian则是低地址存放最低有效字节(LSB)。

用文字说明可能比较抽象,下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:

Big Endian
低地址 高地址
高位字节 低位字节
—————————————–>
| 12 | 34 | 56 | 78 |


+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
低地址 高地址
低位字节 高位字节
—————————————–>
| 78 | 56 | 34 | 12 |

从上面两图可以看出,采用big endian方式存储数据是符合我们人类的思维习惯的。
而little endian,^&*,见鬼去吧 -_-|||
但是目前应该little endian是主流,因为在数据类型转换的时候(尤其是指针转换)不用考虑地址问题。

PS:
big endian与little endian,这两个术语来自于 Jonathan Swift 的《《格利佛游记》《Gulliver’s Travels》,其中交战的两个派别无法就应该从哪一端--小端还是大端--打开一个半熟的鸡蛋达成一致。:) Blefuscu帝国的国民被根据吃鸡蛋的方式划分为两个部分:一部分在吃鸡蛋的时候从鸡蛋的大端(big end)开始,而另一部分则从鸡蛋的小端(little end)开始。
在那个时代,Swift是在讽刺英国和法国之间的持续冲突,Danny Cohen,一位网络协议的早期开创者,第一次使用这两个术语来指代字节顺序,后来这个术语被广泛接纳了

摘自《深入理解计算机系统》


其实大部分人在实际的开发中都很少会直接和字节序打交道。唯有在跨平台以及网络程序中字节序才是一个应该被考虑的问题。


为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则唯一采用big endian方式来存储数据。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?就拿上面的0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,由于JAVA采取big endian方式存储数据,很自然的它会将你的数据翻译为0x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。


无独有偶,所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。x86的CPU使用的是LE(Windows中称为“主机字节序”),而SocksAddr中使用的则是BE(就是“网络字节序”),所以在使用网络编程时需要使用htns,htnl,nths,nthl来倒字节序。


IBM的370种大型机、大多数基于RISC的计算机以及Motorola微处理器使用的是Big-endian顺序,TCP/IP协议也是。而Intel的处理器和DEC公司的一些程序则使用的Little-endian方式。

另附:
endian的由来: URLhttp://www.eygle.com/digest/2007/01/whats_mean_endian.html
endianess: URLhttp://en.wikipedia.org/wiki/Endianness
浮点数存储格式:URLhttp://tb.blog.csdn.net/TrackBack.aspx?PostId=532155

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

您正在使用您的 WordPress.com 账号评论。 登出 /  更改 )

Google photo

您正在使用您的 Google 账号评论。 登出 /  更改 )

Twitter picture

您正在使用您的 Twitter 账号评论。 登出 /  更改 )

Facebook photo

您正在使用您的 Facebook 账号评论。 登出 /  更改 )

Connecting to %s