arm中的数据对其小结

一、简介:

Like other RISC architectures, ARM and Thumb processors are designed to efficiently access aligned data, that is, words that lie on addresses that are multiples of four, and halfwords that lie on addresses that are multiples of two. Such data is located on its natural size boundary。

note:

字(Word):在ARM体系结构中,字的长度为32位,而在8位/16位处理器体系结构中,字的长度一般为16位。

半字(Half-Word):在ARM体系结构中,半字的长度为16位,与8位/16位处理器体系结构中字的长度一致。

字节(Byte):在ARM体系结构和8位/16位处理器体系结构中,字节的长度均为8位。

arm中的数据对其方式可以分为三种类型:

1、Natural alignment

这种方式是编译器默认的方式。为了加快对数据的访问速度,编译器会数据进行对齐。这一部分的内容可以参考我的另一篇博客:结构体的对齐访问

"Such data is located on its natural size boundary",这句话应该怎么理解呢?看到一篇文章写的不错,粘过来大家参考:在32位嵌入式系统中,单字节对象是1字节对齐的;双字节对象是2字节对齐的;四字节对象是4字节对齐的;其它结构体或共同体对象是8字节对齐的。也就是说,当你定义一个单字节对象时,该对象的起始地址可以是任何整数;当你定义一个双字节对象时,该对象的起始地址必定是2的倍数的整数;当你定义一个四字节对象时,该对象的起始地址必定是4的倍数的整数;当你定义一个结构体或共同体对象时,该对象的起始地址必定是8的倍数的整数。以上说的对象包括“结构体或共同体对象的成员对象”。

ref:http://www.51hei.com/bbs/dpj-80946-1.html

2、Known but non-natural alignment

Natural alignment这种方式加快了数据的获取速度,但是牺牲了一定的空间。当可用的空间有限的时候,我们可以使用__packed修饰符或者#pragma pack(n)编译指令来取消自动对齐和数据填充。

 

3、Unknown alignment

Unknown alignment这种对齐方式是对于指针变量而言的。当一个指针变量指向一个non-natural alignment类型的变量,且这个指针变量使用__packed或者#pragma pack(n)进行了修饰,这种情况就称之为Unknown alignment

 

All accesses to data in memory can be classified into the following categories:

  • Natural alignment, for example, on a word boundary at 0x1000. The ARM compiler normally aligns variables and pads structures so that these items are accessed efficiently using LDR and STR instructions.
  • Known but non-natural alignment, for example, a word at address 0x1001. This type of alignment commonly occurs when structures are packed to remove unnecessary padding. In C and C++, the __packed qualifier or the #pragma pack(n) pragma is used to signify that a structure is packed.
  • Unknown alignment, for example, a word at an arbitrary address. This type of alignment commonly occurs when defining a pointer that can point to a word at any address. In C and C++, the __packed qualifier or the #pragma pack(n) pragma is used to signify that a pointer can access a word on a non-natural alignment boundary.

 

二、armcc编译器支持的和数据对齐相关的指令

2.1、__packed 修饰符

The __packed qualifier sets the alignment of any valid type to one. This enables objects of packed type to be read or written using unaligned accesses.

__packed修饰符设置数据的对齐方式为1字节对齐。

__packed常用的使用方法如下:

  • __packed修饰结构体

For efficiency, fields in a structure are located on their natural size boundary. This means that the compiler often inserts padding between fields to ensure they are aligned.

When space is at a premium, the __packed qualifier can be used to create structures without padding between fields.

__packed修饰结构体有两种方式:

方式1:修饰整个结构体

__packed struct mystruct
{
char c;
short s;
} // not recommended

这种方式官方是不推荐的:Declaring an entire struct as __packed typically incurs a penalty both in code size and performance.具体原因看下面实例的反汇编代码!

方式2:修饰结构体中的元素

struct mystruct
{
char c;
__packed short s; // recommended
}

实例分析:

In the disassembly of the unpacked struct in Table 5-10, the compiler always accesses data on aligned word or halfword addresses. The compiler is able to do this because the struct is padded so that every member of the struct lies on its natural size boundary.

In the disassembly of the __packed struct in Table 5-10, the fields one and three are aligned on their natural size boundaries by default, and so the compiler makes aligned accesses. The compiler always carries out aligned word or halfword accesses for fields
it can identify are aligned. For the unaligned field two, the compiler uses multiple aligned memory accesses (LDR/STR/LDM/STM), combined with fixed shifting and masking, to access the correct bytes in memory. The compiler calls the AEABI runtime routine __aeabi_uread4 for reading an unsigned word at an unknown alignment to access the field four, because it is not able to determine that the field lies on its natural size boundary.

In the disassembly of the struct with individually packed fields in Table 5-10, the fields one, two, and three are accessed just as they are in the case where the entire struct is qualified as __packed. In contrast to the situation where the entire struct is packed, however, the compiler makes a word-aligned access to the field four, because the presence of the __packed short within the structure helps the compiler to determine that the field four lies on its natural size boundary.

note: The -Ospace and -Otime compiler options control whether accesses to unaligned elements are made inline or through a function call. Using -Otime results in inline unaligned accesses, while using -Ospace results in unaligned accesses made through function calls.

上述的反汇编代码是c code在-O2的情况下进行编译的。

  • __packed修饰联合体

The same principles apply to unions. You can declare either an entire union as __packed, or use the __packed attribute to identify components of the union that are unaligned in memory.

修饰联合体和修饰结构体的使用方法一样,同样可以对整个联合体进行修饰或者对联合体中的某个元素进行修饰

 

  • __packed修饰指针变量

By default, the ARM compiler expects conventional C pointers to point to an aligned word in memory, as this enables the compiler to generate more efficient code.
If you wish to define a pointer that can point to a word at any address, then you must specify this using the __packed qualifier when defining the pointer. For example:

通常情况下,编译器期望指针变量指向的是内存中对齐的变量。当需要定义一个指针变量指向内存中任意地址的数据时,必须使用__packed对指针变量进行修饰,这样编译器才会对指针变量进行正常的解引用,否则会出错!

__packed int *pi; // pointer to unaligned int

 

2.2、__attribute__((packed))

The packed variable attribute specifies that a variable or structure field has the smallest possible alignment. That is, one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute.

struct
{
    char a;
    int b __attribute__ ((packed));
} Variable_Attributes_packed_0;

 

2.3、#pragma pack(n)

This pragma aligns members of a structure to the minimum of n and their natural alignment. Packed objects are read and written using unaligned accesses.

n is the alignment in bytes, valid alignment values being 1, 2, 4 and 8.The default is #pragma pack(8).

typedef struct
{
    char a;
    int b;
} S;


S var = { 0x11, 0x44444444 };

#pragma pack(2)
typedef struct
{
    char a;
    int b;
} SP;

SP pvar = { 0x11, 0x44444444 };

SP is a 6-byte structure. There is no padding after b.

 

 

 

ref:

https://www.keil.com/support/man/docs/armcc/armcc_chr1359124968737.htm

《DUI0205I_rvct_compiler_user_guide.pdf》

《DUI0348B_rvct_compiler_ref_guide.pdf》

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值