大小端和字节序在嵌入式软件开发过程中经常会遇到,涉及数据传输、存储、通信等方面。下面我将与大家分享相关的知识。
回顾字节序
字节序指的是字节在计算机中存储时的顺序,以及输入(输出)时的顺序是先到的在前还是后到的在前。
我们以数据0x01020304为例:
-
在大端CPU中,数据将按照0x01(address + 0),0x02(address + 1),0x03(address + 2),0x04(address + 3)的顺序进行存储。
-
在小端CPU中,数据将按照0x04(address + 0),0x03(address + 1),0x02(address + 2),0x01(address + 3)的顺序进行存储。
之前给大家分享过一篇文章《CPU大小端之分》讲述了大小端的细节内容,不了解的读者可以阅读了解一下。
如果你的程序使用简单的数据结构(例如“ int”和“ short”),则没有什么麻烦。但是,如果数据结构类似于以下示例,则可能会遇到问题。
union {
unsigned int dat;
unsigned char c[4];
}X;
void foo( ) {
int t0;
X.dat = 0x01020304;
t0 = X.c[0];
・・・
}
在大端 CPU 中编译并执行此代码时, t0”的值为0x01。在小端CPU中, t0”的值为0x04。
那么问题来了:要想使存储顺序从大端,变为小端,怎么办呢?
方法其实有很多种,这里讲讲针对IAR的两种方法:
-
使用__big_endian关键字。 -
使用__REV, __REV16, __REVSH, RBIT函数。
使用__big_endian关键字
IAR中__big_endian关键字提供了一种方便的方式来将应用程序从big-endian移植到little-endian。
__big_endian关键字用于访问以big-endian字节顺序存储的变量,而与应用程序其余部分使用的字节顺序无关。在ARMv6或更高版本进行编译时,可以使用__big_endian关键字。
只需添加__big_endian关键字即可,如:
____big_endian union {
unsigned int dat;
unsigned char c[4];
}X;
void foo( ) {
int t0;
X.dat = 0x01020304;
t0 = X.c[0];
・・・
}
修改后的代码在低位字节CPU中编译和执行,变量“ t0”为0x01。
修改后的代码在低位字节CPU中编译和执行,变量“ t0”为0x01。
**
**
注意:此关键字不能用于指针。同样,此属性不能在数组上使用。
同时,关键字__big_endian插入REV指令以交换字节数据,REV指令的插入会影响代码大小和执行时间。
关键字具有限制,不能应用于复杂的数据结构,比如以下代码会生成错误:
__big_endian
union {
unsigned long dat;
unsigned char c[4];
struct {
unsigned long a0: 1;
unsigned long a1: 1;
unsigned long a2: 2;
unsigned long a3: 4;
unsigned long a4: 8;
unsigned long a5: 16;
}s;
} f1_dat2;
使用__REV, __REV16, __REVSH, RBIT函数
大端和小端之间的字节顺序差异只是顺序,因此我们需要做的是更改字节顺序,我们再次以变量0x01020304为例:
我们可以通过代码实现交换功能,比如:
typedef unsigned long uint32_t;
uint32_t bswap_32(uint32_t x) {
uint32_t t = x;
uint32_t s;
s = ( (((uint32_t)(t) & (uint32_t)0x000000ffUL) > 8) |
(((uint32_t)(t) & (uint32_t)0xff000000UL) >> 24) );
return s;
}
通过这种方式实现,将导致消耗更多时间和代码大小。
在C代码中,我们通常编写内联汇编代码实现交换。IAR有种内部函数可以实现该功能。
比如下面交换功能:
代码如下:
#include
void x1( void ) {
s2 = __REV(s1);
s3 = __REV16(s1);
s4 = __REVSH(s1);
}
以上就是在IAR中实现大小端字节序的迁移方法,感兴趣的读者可以在IAR中编码测试一下。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !