也谈大端模式(big endian)和小端模式(little endian) (二) 理论与实例一

【PCIe 5.0 - 6】PCIe 事务层详解2 - 带Data Payloads的TLP封装规则 带Data Payloads的TLP封装规则 阅读详情
static union 
{     
    char c[4]; 
    unsigned long l;
 } endian_test = { { 'l', '?', '?', 'b' } };


#define ENDIANNESS ((char)endian_test.l)

    我们可以在Linux内核源码中找到以上代码,这个宏的意图显而易见:小端机器输出 l (little endian), 大端机器输出 b(big endian)。我们分别在PC机和PowerPC的机器上来试验一下:

#include <stdio.h>

static union 
{
     char c[4]; 
     unsigned long l; 
}endian_test = { { 'l','?','?','b' } };

#define ENDIANNESS ((char)endian_test.l)

int main()
{
    printf("ENDIANNESS = %c\n", ENDIANNESS);
    printf("addr of c[0] = 0x%x, c[3] = 0x%x, l = 0x%x\n", &endian_test.c[0], &endian_test.c[3], &endian_test.l);
    return 0;
}

 

PC:

ENDIANNESS = l
addr of c[0] = 0x8049714, c[3] = 0x8049717, l = 0x8049714

PowerPC:

ENDIANNESS = b
addr of c[0] = 0x7ff18f38, c[3] = 0x7ff18f3b, l = 0x7ff18f38

    结果不言而喻,但这不是我们的目的。我们注意到,不管是小端的PC机还是大端的PowerPC,联合体中c[0]的地址都是跟变量 l  的地址是一样的,并且都是在低地址。这也符合“联合体union成员的存放顺序是从低地址开始的”这一描述(注意这句话是不区分大小端的机器的,也就是说不论大端小端机器,这句话都是成立的)。

    我们继续分析,根据endian_test的赋值方式,以及上面给出的c[0]的地址,显然不管大端还是小端,c[0]中存放应该都是字符 'l'。但是对于宏ENDIANNESS,大端和小端的机器的结果却不一样,这又是为什么呢?我们还是来看下汇编代码吧:

 

PC上的汇编代码:

$ gcc -S test-endian.c
$ cat test-endian.s
	.file	"test-endian.c"
	.data
	.align 4
	.type	endian_test, @object
	.size	endian_test, 4
endian_test:
	.byte	108
	.byte	63
	.byte	63
	.byte	98
	.section	.rodata
.LC0:
	.string	"ENDIANNESS = %c\n"
	.align 4
.LC1:
	.string	"addr of c[0] = 0x%x, c[3] = 0x%x, l = 0x%x\n"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	andl	$-16, %esp
	subl	$16, %esp
	movl	endian_test, %eax
	movsbl	%al, %eax
	movl	%eax, 4(%esp)
	movl	$.LC0, (%esp)
	call	printf
	movl	$endian_test, 12(%esp)
	movl	$endian_test+3, 8(%esp)
	movl	$endian_test, 4(%esp)
	movl	$.LC1, (%esp)
	call	printf
	movl	$0, %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (GNU) 4.7.0 20120507 (Red Hat 4.7.0-5)"
	.section	.note.GNU-stack,"",@progbits

    我们注意到这里:

endian_test:

        .byte 108
        .byte 63
        .byte 63
        .byte 98
        .section rodata

    容易看出,这就是endian_test的初始值, 'l','?','?','b' 对应的ASCII码。接下来就是:

        movl endian_test, %eax
        movsbl %al, %eax
        movl %eax, 4(%esp)
        movl $.LC0, (%esp)
        call printf
   

     这段代码也比较简单,关键就是movl endian_test, %eax和movsbl %al, %eax 这两句,将endian_test位置取得的四个字节中的最低8位放到寄存器eax中,显然这个值应该是108,即 'l'。剩下的就是给 printf 准备参数。

PowerPC上的汇编代码:

 

    PowerPC的汇编有点特殊,这里不再详述,有兴趣的同学可以查阅参考资料中的相关内容。可以看到,开始的四个字节跟PC上的汇编是一样的,都是存放endian_test的初始值,并且顺序也是一样的。下面来看关键的部分:

        lis 9, endian_test@ha
        lwz 0, endian_test@l(9)       /* 与上面一句合起来表示从 endian_test 处读取一个32位数放到寄存器0中 */
        rlwinm 0, 0, 0, 0xff                /* 只保留寄存器0的最低8位 */
        lis 9, .LC0@ha
        la 3, .LC0@l(9)
        mr 4, 0                                /* 参考上面PC的汇编可知这三句也是给 printf 准备参数*/
        bl printf

    显然,问题的关键就是 movl endian_test, %eax 和   lwz 0, endian_test@l(9),执行完这两句后,我们可以想象,PC的寄存器eax和PowerPC的寄存器0的值一定是相反的。 对应《也谈大端模式(big endian)和小端模式(little endian) (一) 》中的内容,对于同样一个32位数字如0x11223344,该值在大端和小端机器在内存中的存放顺序不同,但当CPU按照32位读出时,值都是0x11223344;而这里的情况是由于用到了联合体union,所以大端和小端的endian_test在内存中的存放顺序相同,当然结果也正好是取出的值是不同的。注意这里的不同是CPU的行为不同,也就是说,内存中同样的一个数字(指存储顺序一样的情况),大小端按照32位读取到寄存器中的时候,值恰好是相反的。而这只是在寄存器中的值发生了改变,内存中的值是没有变化的,因为只是读取数据嘛。

    从另一个角度说,无论对于大端和小端的机器,c[0]的值都是字符 'l',也证明了这种情况下的存放顺序是一样的。存放顺序相同,按四字节取出的话,大小端的机器值当然是不一样的。

 

参考资料:

【1】Linux PowerPC详解:核心篇

【2】PowerPC 汇编简介 http://www.ibm.com/developerworks/cn/linux/hardware/ppc/assembly/index.html

【3】PowerPC rlwinm指令的运算过程 http://blog.chinaunix.net/uid-361890-id-1564927.html

8、计算机中的大端存储(Big-Endian)和小端存储(Little-Endian) 计算机中的大端存储(Big-Endian)和小端存储(Little-Endian)是两种不同的多字节数据在内存中的排列方式,直接影响数据的读写、网络传输和跨平台兼容性 阅读详情

相关推荐

大端和小端(Big endian and Little endian):1、大端小端转换方法 2、检测方法

对于整型、长整型等数据类型 - Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据 - Little endian 则相反,它认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放。

专注于计算机研发知识和资讯分享 1万+

基础笔记3 —— 关于大小端数据存储方式的转换及测试说明

文章目录说明1.大小端概念2.各自的优势3.现阶段大小端模式的使用情况[^1]4.测试所用设备的数据存储方式4.1 使用union测试机器大小端4.2 使用指针测试5.大小端的转换 说明 为什么会关心大小端问题 ? 在控制系统中,由于CPU架构以及编译器等因素决定了数据的存储方式,不同的存储方式,其数据的发送/解读方式需要使用响应的方法。 因此,在数据传输时,我们有必要弄清楚两台或多台设备的存储方...

罗伯特祥的博客 2106

智能座舱音频系统集成与调试:从芯片选型到音质优化实战

在智能座舱域控制器架构中,音频系统已从简单的功放加扬声器演进为SoC、数字音频总线、外部DSP与多通道功放协同的复杂子系统。TDM总线的时隙分配、PDM麦克风阵列的信号完整性,以及AEC回声消除算法如何与硬件协同,直接决定多音区体验和语音交互的可靠性。工程实践中,音频调试的关键在于先理顺供电、接地、时钟与数据路由,再针对功放削波、采样率失配、TDM slot错位等典型问题进行系统性排查。从芯片选型到系统级指标验收,只有将音频链路视为整车电子电气架构的一个协同整体,才能真正实现从“响”到“好听”的跨越。本文结

weixin_30162121的博客 371

PCIe - 那点点事

各位看官,这是我拷贝过来的,作为学习笔记(本人对图比较感兴趣,你说我懒也行,上图,这个看着舒服易懂): 1. Wire, lane, link 啥关系 注: PCIe 每条lane有1个双向通道(一个发,一个收),4条差分线 2. PCI/PCIe 各式插槽 3. PCI/PCIe 各代传输速率 4. PCIe high level diagram (出...

weixin_30294709的博客 338

OpenCode:开源代码智能代理平台的全面解析

OpenCode是一个开源代码智能代理平台,采用模块化微服务架构,支持多种AI模型集成。该系统包含前端交互层、代理服务层和模型集成层,提供Build、Plan和General三种代理模式,分别负责代码编写、分析和复杂任务处理。OpenCode支持跨平台安装,具备权限验证、上下文感知等安全机制,并集成LSP协议实现深度代码理解。相比竞品,其开源特性、终端优先设计和提供商无关架构具有明显优势,适用于个人开发、团队协作等多种场景,为开发者提供强大的AI辅助编程能力。

Aaron_945的博客 1425

Excel基金净值自动更新:手把手教你用Power Query抓取天天基金网数据(含常见错误修复)

本文详细介绍了如何利用Excel内置的Power Query工具,从天天基金网自动抓取基金净值数据,实现表格数据的自动刷新。通过手把手教程,您将学会构建参数化查询、整合多基金数据、计算持仓盈亏,并解决网页结构变动等常见错误,最终打造一个专属的、可自动更新的基金监控仪表盘,彻底告别手动更新。

xx56789的博客 730

PCIe学习笔记(6)

◦大端序示例:对于一个64位(8字节)的Swap Request,目标位置为100h,目标内存为大端序格式,头后的第一个字节写入位置107h,第二个字节写入位置106h,以此类推,最后一个字节写入位置100h。◦小端序示例:对于一个64位(8字节)的交换请求,目标位置100h,目标内存为小端序格式,头后的第一个字节写入位置100h,第二个字节写入位置101h,依此类推,最后一个字节写入位置107h。不能超过由接收设备控制寄存器的Max_Payload_Size字段中的值指定的长度。,该字段作为DW的整数。

yh_wrew的博客 811

STM32 烧录报错Invalid ROM Table

STM32 烧录报错Invalid ROM Table

热爱科技,物联,程序开发等 1735

【C语言笔记】【小技巧系列】 判断字节序

BYTE_ORDER宏定义BYTE_ORDER表示当前机器的字节序,BYTE_ORDER的值被定义为,BIG_ENDIAN或者PDP_ENDIAN的其中之一。其中宏定义表示Little-Endian小端,宏定义BIG_ENDIAN表示Big-Endian大端,宏定义PDP_ENDIAN表示PDP-Endian。使用BYTE_ORDER需要包含头文件。使用BYTE_ORDER}或者#endif}==#endif}==#endif}宏定义与BYTE_ORDER,或者。...

2386

Apollo Planning决策规划算法代码详细解析 (1):Scenario选择

本文重点讲解Apollo代码中怎样配置Scenario以及选择当前Scenario,Scenario决策是Apollo规划算法的第一步,本文会对代码进行详细解析,也会梳理整个决策流程,码字不易,喜欢的朋友们麻烦点个关注与赞。 在本文你将学到下面这些内容: 规划器planer的种类; 规划器planer的主要函数及逻辑; 场景管理类ScenarioManager的运行机制; 场景注册方法; 场景决策流程,如何选择当前场景 详细的apollo决策规划代码分析 代码具体过程如下: 1、Scenar

自动驾驶Player的博客 1万+

C#上位机实战:Modbus RTU串口通信(CRC校验+超时重发完整实现)

在工业自动化上位机开发中,Modbus RTU是串口通信的事实标准协议,SerialPort是 .NET 平台操作串口的原生类,无需依赖第三方库即可实现基础通信。实际项目中,工控现场存在电磁干扰、串口丢包、设备响应延迟等问题,CRC 数据校验用于保证报文完整性,超时重发机制用于提升通信稳定性。本文从零封装一套可直接落地的 Modbus RTU 通信组件,包含完整的校验算法、超时控制、重发逻辑,并配套 WinForm 演示界面。本文基于 C# 原生SerialPort类,实现了一套生产可用。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 392

大端模式(big-endian)与小端模式(little-endian)

参考自大端模式与小端模式 大端模式是指数据的低位保存在内存的高地址中,而数据的高位保存在内存的低地址中. 小端模式是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。 大小端模式的由来在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器

jason_cuijiahui的博客 2万+

为什么idea已经改了UTF-8还是乱码,如何解决?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!

**My Coding Family** 1578

大端模式和小端模式的区别

一、什么是大端和小端 Big-Endian和Little-Endian的定义如下: Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。 Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。 举一个例子,比如数字0x12 34 56 78在内存中的表示形式为: 1)大端模式: 低地址 -----------------> 高地址 0x12 | 0x34 | 0x56 | 0x78 2)小端模式: 低地址 ------

weixin_48067074的博客 5117

FineReport FCP模拟题五

新建决策报表,设置 移动端 格式,采用绝对布局。数据来源:FRDemo中的订单表/雇员表。

Davina_yu的博客 725

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

java -- Big Endian and Little Endian 大端和小端概念讲解及如何转换

字节是计算机中数据处理的基本单位。 计算机中以字节为单位存储和解释信息,规定一个字节由八个二进制位构成,即1个字节等于8个比特(1Byte=8bit)。 计算机进行数据处理时,一次存取、加工和传送的数据长度称为字(word)。一个字通常由一个或多个(一般是字节的整数位)字节构成。 但并非所有计算机都以相同的顺序存储由多字节值组成的字节。考虑一个由2个字节组成的16位因特网。存储该值有两种方式 本文针对大小端的概念进行讲解,并提供如何进行大小端转换的示例

penriver的博客 5349

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

大端(Big Endian)与小端(Little Endian)详解

大端(Big Endian)与小端(Little Endian)简介 /////////////////////////////////////////////////////// 1. 你从哪里来? 端模式(Endian)的这个词出自JonathanSwift书写的《格列佛游记》。这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为BigEndian,从尖头开始

凌风探梅的专栏 1万+

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

大小端字节序(Big Endian和Little Endian)

那么何为字节序(Endia)呢? Big Endian是指低地址存放最高有效字节(MSB),而Little Endian则是低地址存放最低有效字节(LSB)。 大端模式 所谓的大端模式(Big-endian),是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放; 例子: 0000430: e684 6c4e 0100 1800 53ef 0100 0100 0000 0000440: b

熊浪的博客 6960

【协议森林】详解大端(big endian)与小端(little endian)

1、字节序 字节顺序,又称端序或尾序(英语:Endianness)。在几乎所有的机器上,多字节对象都被存储为连续的字节序列。例如在C语言中,一个类型为int的变量x地址为0x100,那么其对应地址表达式&x的值为0x100。且x的四个字节将被存储在存储器的0x100, 0x101, 0x102, 0x103位置,这就是所谓的字节序。字节存放的顺序有两种模式:大端模式和小端模式。 2、大小端...

平凡的世界 4522

大端模式Big Endian和小端模式Little Endian以及浮点数在内存中的存储

大端模式和小端模式存放数据的区别很简单:大端模式先存放数据的高位字节,小端模式先存放数据的低位字节。比如 int a=0x01234567,a所占的四个字节16进制标示:01 23 45 67。在Linux系统中,使用命令:```bashlscpu```输出:```bashArchitecture:          x86_64CPU op-mode(s):        32-bit, 64-...

bdss58的专栏 8495

大端存储(Big-Endian)和小端存储(Little-Endian)讲解

特性大端存储 (Big-Endian)小端存储 (Little-Endian)最高有效字节 (MSB)存储在最低内存地址存储在最高内存地址最低有效字节 (LSB)存储在最高内存地址存储在最低内存地址内存顺序数值高位 -> 低地址,数值低位 -> 高地址数值低位 -> 低地址,数值高位 -> 高地址直观性高(内存转储顺序即数值顺序)低(内存转储顺序是数值的逆序)CPU运算亲和性一般可能更好(从低位开始运算)网络传输标准是(网络字节序)否 (需转换为网络字节序)常见架构。

曾经也曾立志 2278

Big Endian(大端)和 Little Endian(小端)模式

文章目录1、字符表示(编码)2、什么是字节序3、大小端模式的区别举个例子如何 C 编程判断CPU是大端还是小端模式例题一例题二:大端模式向小端模式发送数据4、字节序转换函数 核心就是:一个是数据字节顺序,一个内存存储地址顺序 为什么会有 大端模式和小端模式的区别的,这是由于编码的原因,因此,先大致介绍一下编码: 1、字符表示(编码) 在之前的计算机中,一般都是用 ASCII 码,但是其只能表示 2^7 = 128 个不同的字符。(仅仅只能表示 英文) 随着计算机的发展,计算机要表示不同国家的文字,比如

Mikchy的博客 2513

大端模式(Big-Endian)和小端模式(Little-Endian)

大端模式(Big-Endian)和小端模式(Little-Endian)是计算机科学中用于描述多字节数据的字节序(即字节的排列顺序)的术语。这两种模式定义了数据在内存中如何存储和读取,特别是在涉及多字节数据类型(Int ,Float)时。

申徒嘉的专栏 1352

大端 和 小端(Big-endian和Little-endian )

战争开始是由于以下的原因:我们大家都认为,吃鸡蛋前,原始的方法是打破鸡蛋较大的一端,可是当今皇帝的祖父小时候吃鸡蛋,一次按古法打鸡蛋时碰巧将一个手指弄破了,因此他的父亲,当时的皇帝,就下了一道敕令,命令全体臣民吃鸡蛋时打破鸡蛋较小的一端,违令者重罚。叛乱平息后,流亡的人总是逃到那个帝国去寻救避难。关于这一争端,曾出版过几百本大部著作,不过大端派的书一直是受禁的,法律也规定该派的任何人不得做官。Cohen,一位网络协议的早期开创者,第一次使用这两个术语来指代字节顺序[25],后来这个术语被广泛接纳了。

二分掌柜的 8926

python3大端、小端(Big Endian、LittleEndian)编码

大端模式,小端模式指的是数据在内存地址中存储的顺序不同。一般操作系统都是小端,而通讯协议是大端的,所以我们在传输数据时,需要将数据转码。今天在调接口时,就遇了一个这样的接口: 将双字节文字使用Big Endian编码后,转为16进制HEX字符串传输。 这个描述让我费了好大功夫去搜python3应该怎样实现。其实就是分两步: 1. 将内容使用utf-16-be编码去encode。 2. 将en............

蘑菇猎手的专栏 2万+

大端与小端

摘要: 端模式(Endian)源于《格列佛游记》中鸡蛋敲开方式的分类,分为大端(Big-Endian)和小端(Little-Endian)。大端模式高地址存低字节,符合人类读写习惯;小端模式低地址存低字节,便于强制类型转换。CPU的端模式由硬件架构决定(如x86为小端,PowerPC为大端),网络协议采用大端。两者各有优劣:大端易判正负,小端转换高效。可通过代码判断端模式,并提供宏和函数实现大小端转换。端模式选择取决于具体应用场景,无绝对优劣之分。

人无远虑,必有近忧 6883
上一篇: 也谈零拷贝(一) 抛砖篇
下一篇: 通过/dev/mem进行恶意代码注入
linuxdrivers
博客等级 码龄16年 147粉丝 14原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值