首页 > 其他分享 >计算机系统中的大端模式和小端模式

计算机系统中的大端模式和小端模式

时间:2023-05-06 16:14:21浏览次数:41  
标签:小端 存储 字节 模式 地址 处理器 大端

  最近工作中有用到一个知识点,就是大小端,当然这是一个小的知识点,为什么写一个博文呢,我其实是想测试一下chatGPT,所以我开始将自己的想法告诉这个chatbot,让他给我一些写博文的建议,并且给我解答了一些疑惑,今天将自己的学习笔记整理出来展示给大家(by the way,一个有用的搜索引擎和chatbot对我们的工作有着事半功倍的作用,并且它的思路很明显比我更好,如果只是单纯的用在学习上,我觉得这个简直是百科全书)。

  废话不多说了,正文开始。

1,什么是大小端?

  在计算机中,字节序指的是在存储器中,多字节数据的字节存放顺序。大小端是计算机体系结构中的一个概念,用于表示在多字节数据类型中,字节的顺序。在不同的计算机体系结构中,字节顺序可能不同。一些处理器将最高位字节存储在地址最低的位置,这被称为“大端字节序”(高位字节排放在内存的低地址端,低位字节排放在内存的高地址端),而另一些处理器将最低位字节存储在地址最低的位置,这被称为“小端字节序”(低位字节排放在内存的低地址端,高位字节排放在内存的高地址端)。

  例如,假设我们要存储十六进制数0x12345678(十进制数为305419896),在大端字节序下,它的存储顺序为:

12 34 56 78

  而在小端字节下,则为:

78 56 34 12

   以上从左到右=》 低地址(高位)到高地址(低位)。偷个图:

 

2,大小端的历史原因和发展

2.1 为什么会有大小端之分?

  大端和小端的概念最初由IBM的工程师Danny Cohen提出。这两种字节序最初是由不同的计算机厂商开发出来的。早期的计算机在内部存储器和CPU之间使用通信线,用于发送和接收数据。这些通信线被设计为双向的,可以在读和写时使用。因此,数据的字节顺序是很重要的。在当时的计算机中,大端字节序被广泛采用。

  这是由计算机体系结构的设计决定的。在早期的计算机设计中,内存是以字(word)为单位进行读写的,字的长度不同,如16位、32位或64位等。在读写数据时,需要确定数据的字节顺序,以便正确地处理数据。在计算机系统中,以字节为单位,所以每个地址单元都对应一个字节,一个字节为8bit。但是在C语言中除了8bit的char外,还有16bit的short,32bit的long。另外对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器大于一个字节,那么必然存在一个如何将多个字节安排的问题。因此就导致了大端存储和小端存储模式。

  在大端字节序中,最高有效位在最低的地址上,符合人类的习惯,容易理解和记忆。而在小端字节序中,最低有效位在最低的地址上,这种方式更容易实现,因为它可以让计算机在处理字节序列时不需要额外的转换操作,只需要按照顺序依次读写即可。

  实际上,不同的处理器架构和操作系统都有不同的字节序规则,例如x86架构的处理器使用小端字节序,而PowerPC架构的处理器使用大端字节序。因此,在进行数据传输或数据交换时,需要考虑数据的字节序,以确保数据的正确传输和解析。

2.2 大小端的发展历史

  大小端(Endian)是指计算机中字节的排列顺序。它分为大端(Big-endian)和小端(Little-endian)。大端表示高位字节存储在低地址,而小端表示低位字节存储在低地址。大小端的发展历史可以追溯到计算机的早期发展阶段。

  1960s:大小端的概念最早可以追溯到20世纪60年代,IBM的System/360系列计算机采用了大端字节序。这种字节序的设计与人类阅读数字的方式相似,即从高位到低位。

  1970s:在20世纪70年代,DEC公司推出了PDP-11系列计算机,采用了小端字节序。小端字节序的优势在于,对于多字节整数的部分访问和计算更加方便,因为低位字节总是存储在最低的地址。

  1980s:随着计算机技术的发展,许多不同的处理器架构开始出现。例如,Motorola 68000系列处理器采用大端字节序,而Intel x86系列处理器采用小端字节序。这导致了计算机领域内的大小端之争。

  1990s:在20世纪90年代,随着网络技术的普及,计算机之间的数据交换变得越来越重要。因此,网络字节序(Network Byte Order)的概念应运而生。网络字节序采用大端字节序,以确保不同处理器架构之间的数据交换能够顺利进行。

  2000s至今:在21世纪,计算机技术继续发展,处理器架构也趋于多样化。许多处理器,如ARM和PowerPC,支持大小端可配置,使得系统设计者可以根据实际需求选择合适的字节序。此外,一些编程语言和库也提供了跨平台的字节序转换功能,以便在不同字节序的系统之间进行数据交换。

  在早期的计算机体系结构中,大端字节序是主流的存储方式。但是,后来随着英特尔处理器的流行,小端字节序逐渐成为主流。英特尔处理器采用小端字节序的主要原因是,其实现简单且效率高。同时,小端字节序的处理方式也更符合人的直观感觉,因为我们通常是从低位到高位依次读取数据。总之,大小端的发展历史反映了计算机技术的演进和处理器架构的多样化。如今,大小端问题已经不再是一个严重的障碍,因为现代处理器和软件都提供了灵活的解决方案来应对字节序差异。

  

3,大小端的实现原理和存储方式

  在计算机中,大端(Big-Endian)和小端(Little-Endian)是两种不同的数据存储方式。下面我们详细学习一下大小端的实现原理和存储方式,具体定义如下:

  大端字节序(Big-Endian):在大端字节序中,数据的高位字节存储在低位地址上,而数据的低位字节存储在高位地址上。这种方式类似于我们人类习惯的顺序,从左到右,高位到低位。

  存储方式:假设我们有一个32位整数0x12345678,其内存地址为0x1000。在大端字节序的系统中,该整数的存储方式如下:

地址            数据
0x1000 -> 0x12 (高位字节)
0x1001 -> 0x34
0x1002 -> 0x56
0x1003 -> 0x78 (低位字节)

  

  小端字节序(Little-Endian):在小端字节序中,数据的低位字节存储在低位地址上,而数据的高位字节存储在高位地址上。这种方式与大端字节序相反,但是在实际应用中也有很多优点,例如可以方便地进行低位对齐。

  存储方式:同样以32位整数0x12345678为例,其内存地址为0x1000。在小端字节序的系统中,该整数的存储方式如下:

地址            数据
0x1000 -> 0x78 (低位字节)
0x1001 -> 0x56
0x1002 -> 0x34
0x1003 -> 0x12 (高位字节)

  

  大小端的实现原理和存储方式主要体现在多字节数据在内存中的排列顺序。大端字节序将高位字节存储在低地址,而小端字节序将低位字节存储在低地址。不同的处理器架构可能采用不同的字节序,因此在进行跨平台数据交换时需要注意字节序的转换。两种字节序的区别在于字节的存储顺序,而不是位的存储顺序。在多字节数据类型(例如整数、浮点数等)存储时,其字节序决定了字节在内存中的排列顺序。

  下面是一个示意图,展示了一个32位整型数在大端和小端字节序下的存储方式:

大端字节序:
0x12345678
+--------+
| 12 | 34|
+--------+
| 56 | 78|
+--------+

小端字节序:
0x12345678
+--------+
| 78 | 56|
+--------+
| 34 | 12|
+--------+

  

4,不同架构的字节序规则

  不同的处理器架构可能采用不同的字节序规则。以下是一些常见处理器架构及其字节序规则:

  Intel x86/x64(IA-32/IA-64): 字节序规则:小端(Little-endian) 说明:Intel x86和x64架构处理器广泛应用于个人计算机和服务器领域。这些处理器采用小端字节序,将低位字节存储在低地址。

  ARM: 字节序规则:大小端可配置(Configurable Endianness) 说明:ARM处理器广泛应用于嵌入式系统和移动设备。ARM架构支持大小端可配置,系统设计者可以根据实际需求选择合适的字节序。大多数情况下,ARM处理器默认采用小端字节序。

  MIPS: 字节序规则:大小端可配置(Configurable Endianness) 说明:MIPS处理器应用于嵌入式系统、网络设备和游戏机等领域。MIPS架构支持大小端可配置,允许系统设计者根据需求选择字节序。通常情况下,MIPS处理器默认采用大端字节序。

  PowerPC: 字节序规则:大小端可配置(Configurable Endianness) 说明:PowerPC处理器应用于嵌入式系统、服务器和游戏机等领域。PowerPC架构支持大小端可配置,允许系统设计者根据需求选择字节序。通常情况下,PowerPC处理器默认采用大端字节序。

  Motorola 68000: 字节序规则:大端(Big-endian) 说明:Motorola 68000系列处理器曾广泛应用于个人计算机、游戏机和嵌入式系统等领域。这些处理器采用大端字节序,将高位字节存储在低地址。

  SPARC: 字节序规则:大端(Big-endian) 说明:SPARC处理器主要应用于高性能计算和服务器领域。SPARC架构采用大端字节序,将高位字节存储在低地址。

  需要注意的是,不同处理器架构的字节序规则可能会影响跨平台数据交换。在进行数据交换时,需要注意字节序的转换,以确保数据的正确性。许多编程语言和库提供了跨平台的字节序转换功能,以便在不同字节序的系统之间进行数据交换。

  简单将上面内容整理一下(方便直接看结论的童靴):

大小端 CPU
Big Endian PowerPC, MIPS, Mac OS, IBM , Sun, Mototola 68000, SPARC
Little Endian x86, x64, DEC, Windows

 

4.1  如何判断机器的字节序

  遇到大小端的问题,我们如何解决呢,首先就是判断机器的字节序(是大端字节序还是小端字节序),然后进行转换。

  给一个C++判断机器字节序的代码:

// Judge the endian of the local system
inline bool isLittleEndian() {
union {
uint32_t i;
char c[4];
} test = {0x01020304};
return test.c[0] == 0x04;
}

  或者下面例子:

#include <iostream>

// 判断机器字节序的函数
bool isLittleEndian() {
    int num = 1;
    char *ptr = reinterpret_cast<char*>(&num);
    return *ptr == 1;
}

int main() {
    if (isLittleEndian()) {
        std::cout << "This machine is Little-endian." << std::endl;
    } else {
        std::cout << "This machine is Big-endian." << std::endl;
    }
    return 0;
}

  下面是一个转换大小端字节序的例子,比如你的机器需要大端,所以处理不同操作系统的时候,你需要考虑先判断系统字节序的,然后不同的需要转换,毕竟我们上面也提到了不同系统字节序不同。

#include <iostream>

// 转换16位整数的字节序
uint16_t swapEndian16(uint16_t value) {
    return (value << 8) | (value >> 8);
}

// 转换32位整数的字节序
uint32_t swapEndian32(uint32_t value) {
    return ((value << 24) & 0xFF000000) |
           ((value << 8) & 0x00FF0000) |
           ((value >> 8) & 0x0000FF00) |
           ((value >> 24) & 0x000000FF);
}

// 转换64位整数的字节序
uint64_t swapEndian64(uint64_t value) {
    return ((value << 56) & 0xFF00000000000000) |
           ((value << 40) & 0x00FF000000000000) |
           ((value << 24) & 0x0000FF0000000000) |
           ((value << 8) & 0x000000FF00000000) |
           ((value >> 8) & 0x00000000FF000000) |
           ((value >> 24) & 0x0000000000FF0000) |
           ((value >> 40) & 0x000000000000FF00) |
           ((value >> 56) & 0x00000000000000FF);
}

int main() {
    uint16_t num16 = 0x1234;
    uint32_t num32 = 0x12345678;
    uint64_t num64 = 0x123456789ABCDEF0;

    std::cout << "Original 16-bit value: " << std::hex << num16 << std::endl;
    std::cout << "Swapped 16-bit value: " << std::hex << swapEndian16(num16) << std::endl;

    std::cout << "Original 32-bit value: " << std::hex << num32 << std::endl;
    std::cout << "Swapped 32-bit value: " << std::hex << swapEndian32(num32) << std::endl;

    std::cout << "Original 64-bit value: " << std::hex << num64 << std::endl;
    std::cout << "Swapped 64-bit value: " << std::hex << swapEndian64(num64) << std::endl;

    return 0;
}

  上面的示例展示了如何在C++中判断机器的字节序以及如何转换大小端字节序。在实际应用中,可能大家需要根据自己的需求对代码进行调整和优化,我自己也是。(当然如果使用python,可能更方便)

5,应用场景

  大小端字节序在计算机系统中有很多应用场景。以下是一些常见的应用场景:
  1. 跨平台数据交换: 当不同字节序的计算机系统需要交换数据时,需要进行字节序转换以确保数据的正确性。例如,网络协议中的数据包在发送和接收时需要进行字节序转换。大多数网络协议(如TCP/IP)采用大端字节序(网络字节序)作为标准。因此,在发送数据时,小端字节序的系统需要将数据转换为大端字节序;在接收数据时,需要将大端字节序的数据转换为小端字节序。
  2. 文件格式: 许多文件格式规定了数据的字节序。例如,BMP图像文件格式规定了数据的字节序。在处理这些文件时,需要根据文件格式的要求进行字节序转换,以确保数据的正确性。
  3. 数据库存储: 在数据库中存储多字节整数时,可能需要考虑字节序问题。不同的数据库系统可能采用不同的字节序。在进行数据迁移或备份时,需要注意字节序的转换。
  4. 外部设备通信: 在与外部设备(如传感器、控制器等)通信时,可能需要进行字节序转换。外部设备可能采用不同的字节序,因此在发送和接收数据时需要进行字节序转换以确保数据的正确性。
  5. 二进制数据处理: 在处理二进制数据(如加密、压缩等)时,可能需要考虑字节序问题。不同的算法可能对字节序有不同的要求。在实现这些算法时,需要根据算法的要求进行字节序转换。
  总之,大小端字节序在计算机系统中有很多应用场景。在处理跨平台数据交换、文件格式、数据库存储、外部设备通信和二进制数据处理等问题时,需要注意字节序的转换,以确保数据的正确性。

标签:小端,存储,字节,模式,地址,处理器,大端
From: https://www.cnblogs.com/wj-1314/p/12133422.html

相关文章

  • Istio数据面新模式:Ambient Mesh技术解析
    摘要:AmbientMesh以一种更符合大规模落地要求的形态出现,克服了大多数Sidecar模式的固有缺陷,让用户无需再感知网格相关组件,真正将网格下沉为基础设施。本文分享自华为云社区《华为云云原生团队:Istio数据面新模式AmbientMesh技术解析》,作者:云容器大未来。如果说在以Kubernetes......
  • Windows11 无法显示卓越性能以及仅有平衡模式一条计划的解决方案
    如果你用的是专业工作站版,且使用了如下命令:Powercfg/DUPLICATESCHEMEe9a42b02-d5df-448d-aa00-03f14749eb61还是无法显示任何多余计划,那么就证明你用的系统版本已经实施了新式待机:ModernStandbyonWindows该模式只可以通过设置-电池电源中设置最佳性能,而无法在控制面板......
  • Django的MVT模式和Spring的MVC模式类比
    Spring的MVC模式MVC: Model-View-Controller 模型-视图-控制器M:数据处理V:界面显示C:逻辑处理最开始用于Desktop程序开发,现在已被广泛使用,包括Web开发。核心思想: 分层,解耦。MVC分离了数据处理和界面显示的代码,使得程序可以在不修改数据处理相关逻辑的前提下......
  • 本地消息表模式
    分布式事务|使用dotnetcore/CAP的本地消息表模式 本地消息表模式本地消息表模式,其作为柔性事务的一种,核心是将一个分布式事务拆分为多个本地事务,事务之间通过事件消息衔接,事件消息和上个事务共用一个本地事务存储到本地消息表,再通过定时任务轮询本地消息表进行消息投递,下......
  • CentOS虚拟机连接外网,NET模式
    大致思路,将主机和CentOS的ip设置成同一网段,并且网关相同,虚拟网络编辑器中的网关也与主机相同1、主机VMnet8的ip设置  2、CentOS的网关和ip设置1)查看网络设备名称 2)进入编辑IP和网关、DNS等进入network-scripts,网络相关的配置文件存放位置/etc/sysconfig/network-scr......
  • 《3D编程模式》写书-第5次记录
    大家好,这段时间我完成了对初稿的第一轮修改,即将开始第二轮的修改这里是所有的的写书记录:《3D编程模式》写书记录本轮修改主要进行了下面方面的修改:修改错误修改了UML错误、文字错误、代码错误等错误隐藏代码的实现细节,进行抽象这一步修改的目的在于使案例中的代码只展示说......
  • vim编辑器模式和命令
    输入命令:yum-yinstallvim*​或者sudoapt-getinstallvim 命令模式按dd键删除当前光标所在行按D键删除当前光标所在行按G键将光标移动到文件的最后按dG键删除当前光标所在行到最后一行按d1G键删除当前光标所在行到第一......
  • 架构师日记-深入理解软件设计模式
    作者:京东零售刘慧卿一设计模式与编程语言1.1什么是设计模式设计模式(Designpattern):由软件开发人员在软件开发中面临常见问题的解决方案,是经过长时间的试验积累总结出来的,它使设计更加灵活和优雅,复用性更好。从实用的角度来看,它代表了某一类问题的最佳实践。设计模式到底解......
  • 青年开发者说:了不起的“桩源”守护者,开启智能充电新模式
    摘要:听来自深圳大学的高校开发者们,分享基于华为云技术创新、收获成功的故事。代码改变世界,2023年华为开发者大赛不容错过!本文分享自华为云社区《青年开发者说:了不起的“桩源”守护者,开启智能充电新模式》,作者:华为云社区精选。“桩源守护者”,一个听起来有点热血、又充满了英雄主......
  • STM32单片机引脚要职能配置为输入或者输出模式,并不能像51一样准双向,那么如何进行但总
    如题随便找个端口举例对应的程序为 难道需要写之后立即初始化为输入?然后赶紧读?然后再赶紧初始化为输出?再往外写?是的,还真他妈就是这么傻逼的操作 ......