理解字节序---大端小端

本篇将以what,why,how三个维度讲述字节序

what

字节序,字面理解可知是字节(Byte)的顺序,是计算机科学针对多字节结构(变量或者文件等)的一种约定,目前分为大端字节序小端字节序

以一个 uint32_t 的4字节类型为例,在该类型的变量中存入0x12345678,从变量的角度来看,0x12为变量的高字节,0x78为变量的低字节。

当变量的  字节存放在内存的  地址,变量的  字节存放在内存的 低 地址时,为小端字节序,如下图:

 

当变量的  字节存放在内存的  地址,变量的  字节存放在内存的  地址时,为大端字节序,如下图:

 

why

定义只是约定,当然可以直接记忆,但是为什么要这么约定?为什么要分成两种字节序?有什么好处?

两种字节序针对两类对象,大端字节序 面向的是 人类小端字节序 面向的是 计算机

大端字节序符合人类阅读的习惯,对字节流的处理也是按照阅读习惯来定义,这样能减少人类的处理负担,因此如网络字节序用的就是大端字节序,当网络socket传输一个多位数时,按照阅读习惯,接收到的是高字节数,因此直接左移8位相加。

小端字节序符合计算机处理的顺序

        1.计算机读取数据不关心格式,仅按照内存地址顺序读取

        2.计算机处理数据从数据低位开始处理,这个也是计算机设计定义的,因此我们需要把变量低地址的数据主动放到内存低地址处,这样计算机取到数据处理才是我们所期望的从低地址开始。如累加操作时,个位相加,进位置位CF,再做十位相加,依次进行累加最终得到结果。

综上,大端字节序面向人类为了简化思维,小端字节序面向计算机为了加快处理速度。

 

how

如何判别计算机是大端字节序还是小端字节序?

可以简单的用一段C语言程序做判断

#include <cstdio>
#include <cstdint>

int main()
{
	uint32_t test_code = 0x12345678;
	uint8_t* first = (uint8_t*)&test_code;  //指针指向变量的内存首字节

	printf("first address value is %x,is %s\n", 
			*first, *first == 0x12 ? "Big Endian" : "Little Endian");
	return 0;
}

可以看到输出为

first指针指向了变量test_code的内存首地址(内存低地址),取出的结果为0x78(变量低地址),由上文定义可知为小端序

 

除了直接查看输出,我们还能通过查看内存方式自己看看存储的情况,这里使用ollyDbg调试上述程序debug模式输出的exe文件,使用ollyDbg打开该exe文件:

右键搜索程序中所有的字符串,这里主要要找printf中的字符串,因为是简单程序没有加密,很容易能够找到调用的地方:

直接查看该变量地址的dump

与程序输出一直,低地址存放着0x78,高地址存放着0x12,因此为小端序。

 

其实计算机并不一定都是小端序,小端序只是计算机的默认字节序,如果需要更改,可以设置相应的控制寄存器进行设置,达到更改字节序的目的,始终记得字节序只是一种约定。

 
发布了19 篇原创文章 · 获赞 7 · 访问量 6934

猜你喜欢

转载自blog.csdn.net/G_METHOD/article/details/104131628