对于字节序小端和大端的思考

最近公司处理器要换核,由小端处理器ARM换成大端处理器POWERPC,bootloader以及kernel的移植工作交给了我,这是一个很有挑战的工作,自己也非常兴奋。

如此一来,当今主流的嵌入式处理器(MIPS ARM PPC)也都算接触过啦。

这几天开始动手做移植,首先要解决的是大小端的差异,进过学习思考,感觉大小端还是很有研究的必要,自己的思考总结记录在此,与大家分享,以备后用。

从网上可以查到的大小端的解释,小端是低端数据存放在低端地址,大端是高端数据存在低端地址。大小端真的就这么简单吗,不是这样的。

字节序大端小端是针对超过一个byte的数据类型在内存中的存储布局来讲的。对象是数据类型的存储布局,为什么要超过一个byte呢,这涉及到内存寻址,内存寻址的最小单位就是byte,一个byte内的数据排布顺序是固定的(小端)。

打个比方,拿我们自己来说,有一句4个字的话,我们是从右向左读,还是从左向右读,这就是我们的字节序啊。

所以对于处理器在操作超过一个byte的数据类型时,如何排布数据在内存中的顺序,就由其字节序来决定。

可以这样理解:

对于小端处理器,如果要寻址一个word型数据,处理器首先由地址总线发出地址,之后对于由32位数据总线(32位处理器)返回的数据,小端处理器认为0-7位数据线是低端数据,而24-31位数据线为高端数据。

  相反,对于大端处理器,寻址一个word型数据,处理器对于数据线返回的数据,认为24-31位数据线为低端数据,而0-7位数据线为高端数据。

字节序大小端还远没有这么简单,对于字节序的理解,我觉得可以分为2种情况:

(1)操作内存,首先说明内存本身是没有字节序一说的,内存中同样一段数据,小端处理器读出来的数据意义和大端处理器读出来的数据意义是不同的,所以其存储数据的顺序是由处理器字节序来决定的。

操作内存,无非就是读和写。那这里又可以分为2种情况,

一种是处理器读处理器写,也就是处理器主动发起对于内存的读写,因为使用同一处理器,采用同样的字节序去读写同一数据(修改其值,进行位操作等)是没有差别的,唯一的差别是在对于同一段内存,读写时操作了不同的数据类型。这种情况就不细说了,因为现在街是大小端的文章都会解释这个问题,这也是验证处理器是大端还是小端很好的方法。

另一种是另一主设备与处理器异步的操作了内存,如DMA,假如处理器由小端改为大端,而外设是小端(我这次的移植就是这种情况),在外围硬件设计不变的情况下(处理器0-31数据线与外设0-31数据线一一对应),外设DMA写入内存的数据,由处理器读取回来,数据就已经被翻转了,已经失去了原来的意义。这也是做大小端移植需要注意的一点。

(2)操作寄存器,这跟DMA一样,也是一个异步操作,现在大部分外设控制器寄存器都是小端设计(这里的设计是指寄存器描述是小端的,数据排布也是小端的),寄存器也可以分为2种。

一种是位意义的寄存器,这种寄存器的每一位都有意义,可能是某种功能的开关,这种寄存器在外设中非常常见。对于这类寄存器,小端处理器操作没有差别,因为字节序一致,但是对于大端处理器,其获得寄存器数据是翻转的,所以对于每一位的定义也是翻转的,不过我们可以通过修改软件上(如kernel)对寄存器的位宏定义来获取其正确的位意义,这一点在做大小端移植时需要注意。

另一种是数据意义的寄存器,这种寄存器上存储的是有意义的数据,如串口收发数据寄存器,网卡DMA描述符首地址寄存器等,对于大端处理器,该类寄存器是无法通过修改位宏定义来保证正确,因为其是一个整体数据,这种寄存器只能是在获取其值后将数据再翻转(大端转小端),来获取寄存器中原有意义的数据,在进行操作。

但是如果是这样的修改,就有一个原子操作的问题了,因为读写寄存器本来是由一条指令完成的,但是现在却添加了翻转操作,在进行读写指令,这就不能保证寄存器读写的原子性。在高性能,中断频发,不停切换的操作系统下,就有可能产生问题。

对于这个问题,也可以在硬件上进行协作,如将处理器的(0-7)(8-15)(16-23)(24-31)与外设的(0-7)(8-15)(16-23)(24-31)进行反接,但是这样也可能有问题,如对于大于1byte却小于4byte的数据,处理器如何获取的问题。

这些在由小端到大端移植的问题我还在探索和学习中,还是很有意思的。

不过对于本来设计为大端,寄存器描述也是大端的外设,与大端处理器相连,就不会有这些问题。也就是说外设与处理器字节序同一,这些棘手的问题都可以避免

时间: 2024-11-06 15:41:02

对于字节序小端和大端的思考的相关文章

内存对齐,大端字节   序小端字节序验证

空结构体:对于空结构体,就是只有结构体这个模子,但里面却没有元素的结构体. 例: typedef struct student { }std: 这种空结构体的模子占一个字节,sizeof(std)=1. 柔性数组: 结构体中最后一个元素可以是一个大小未知的数组,称作柔性数组成员,规定柔性数组前面至少有一个元素. typedef struct student { int i; char arr[];     //柔性数组成员 }std: sizeof(std)=4; sizeof求取该结构体大小是

字节与小端、大端法存储。

以下仅为个人学习的记录,如有疏漏不妥之处,还请不吝赐教. 字节(byte)这个术语由 Werner Buchholz在1956年创造的.在此之前,字节通常称为syllable. 历史上,字节并非一定是8位的,但现在基本都是以8位作为1个字节.最开始字节是用来为字符编码的.C语言中的用char类型为字符编码,占1字节.可是1个字节最多只能存放256组合,也就是说,1个字节最多能表示256种字符.因此需要多个字节来表示数据.这就引出一个问题. 多字节数据怎么存储?字节的排列顺序? 在几乎所有的机器中

内存对齐 大端字节,序小端字节序验证

空结构体:对于空结构体,就是只有结构体这个模子,但里面却没有元素的结构体. 例: typedef struct student { }std: 这种空结构体的模子占一个字节,sizeof(std)=1. 柔性数组: 结构体中最后一个元素可以是一个大小未知的数组,称作柔性数组成员,规定柔性数组前面至少有一个元素. typedef struct student { int i; char arr[];     //柔性数组成员 }std: sizeof(std)=4; sizeof求取该结构体大小是

1、打印二进制机器码,程序内存分析,大端序小端序,指针数组,数组指针,数组的三种访问方式,typedef,#if-0-#endif,求数组大小,括号表达式

 1.打印二进制机器码(分别表示32位的和64位的) #include <stdio.h> /*按照8位的长度打印一个数值*/ void dis8bit(char val) { int bit = 8; while(bit--) { if(1<<bit&val){ printf("1"); } else { printf("0"); } if(!(bit%4)) printf(" "); } putchar(1

对于思考小端和大端字节顺序

最近,该公司希望改变核心处理器,由小端处理器ARM为大端处理器POWERPC.bootloader以及kernel移植的工作对我来说,这是一个非常具有挑战性的工作.我很兴奋. 如此一来.当今主流的嵌入式处理器(MIPS ARM PPC)也都算接触过啦. 这几天開始动手做移植,首先要解决的是大小端的差异,进过学习思考,感觉大小端还是非常有研究的必要.自己的思考总结记录在此,与大家分享,以备后用. 从网上能够查到的大小端的解释,小端是低端数据存放在低端地址.大端是高端数据存在低端地址.大小端真的就这

htons、htonl与字节序大小端

判断字节序大小端code #include <stdio.h> int main() { if (htons(1) == 1) printf("big endian\n"); else printf("little endian\n"); return 0; } int main() { printf("0x%x\n", htons(0x9225)); printf("0x%x\n", htonl(0x9225))

主机序与网络字节序解析

网络数据流的地址:先发出的数据是低地址,后发出的是高地址 TCP/IP协议规定,网络数据流采用大端(big endian)字节序,低地址存高字节序,高地址低字节序(网络字节序) 主机字节序一般采用小端(little endian)存储,低地址存低字节序,高地址存高字节序 例子: int num=0x0102 01为高字节,02为低字节序小端存储 02 01大端存储 01 02 ntohs() 将一个无符号短整形数从网络字节顺序转换为主机字节顺序. printf("%ld\n",(eit

网络通信之 字节序转换原理与网络字节序、大端和小端模式

原文地址:http://www.cnblogs.com/fuchongjundream/p/3914770.html 一.在进行网络通信时是否需要进行字节序转换? 相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换. 原因如下:网络协议规定接收到得第一个字节是高字节,存放到低地址,所以发送时会首先去低地址取数据的高字节.小端模式的多字节数据在存放时,低地址存放的是低字节,而被发送方网络协议函数发送时会首先去低地址取数据(想要取高字节,真正取得是低

大端法、小端法、网络字节序

关于字节序(大端法.小端法)的定义 <UNXI网络编程>定义:术语“小端”和“大端”表示多字节值的哪一端(小端或大端)存储在该值的起始地址.小端存在起始地址,即是小端字节序:大端存在起始地址,即是大端字节序.