您的位置 首页 编程

ARM的字对齐问题总结

一、啥是字对齐?为啥要字对齐?现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问都可以从任何地址开始,但

一、啥是字对齐?为啥要字对齐?

现代计算机中内存空间都是依照byte区分的,从理论上讲好像对任何类型的变量的拜访都能够从任何地址开端,但实际状况是在拜访特定类型变量的时分经常在特定的内存地址拜访,这便是对齐。

字节对齐的原因大致是如下两条:

1、渠道原因(移植原因):不是一切的硬件渠道都能拜访恣意地址上的恣意数据的;某些硬件渠道只能在某些地址处取某些特定类型的数据,不然抛出硬件反常。

2、功能原因:数据结构(尤其是栈)应该尽或许地在天然鸿沟上对齐。原因在于,为了拜访未对齐的内存,处理器需求作两次内存拜访;而对齐的内存拜访仅需求一次拜访。

二、对齐规矩

每个特定渠道上的编译器都有自己的默许“对齐系数”(也叫对齐模数)。程序员能够经过预编译指令#pragma pack(n),n=1,2,4,8,16来改动这一系数,其间的n便是你要指定的“对齐系数”。
规矩:
1. 数据成员对齐规矩:结构(struct)(或联合(union))的数据成员,榜首个数据成员放在offset为0的当地,今后每个数据成员的对齐依照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
2. 结构(或联合)的全体对齐规矩:在数据成员完结各自对齐之后,结构(或联合)自身也要进行对齐,对齐将依照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
3. 结合1、2可推断:榜首、假如n大于等于该变量所占用的字节数,那么偏移量有必要满意默许的对齐方法,第二、假如n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不必满意默许的对齐方法。

三、X86对齐试验
下面再扼要回忆解释一下上述的对齐规矩,结合实例进行剖析:
1. 数据类型自身的对齐值:关于char型数据,其自身对齐值为1字节,关于short型为2字节,关于int,float,double类型,其自身对齐值为4字节。
2. 结构体的自身对齐值:其成员中自身对齐值最大的那个值。
3. 指定对齐值:#pragmapack(n)来设定变量以n字节对齐方法。n字节对齐便是说变量寄存的开端地址的偏移量有两种状况,榜首、假如n大于等于该变量所占用的字节数,那么偏移量有必要满意默许的对齐方法,第二、假如n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不必满意默许的对齐方法。
4. 数据成员和结构体的有用对齐值:数据成员(数据类型)和数据结构的自身对齐值和指定对齐值中小的那个值,数据成员对齐了数据结构天然也就对齐了。
了解上述四个基本概念,咱们开端评论详细数据结构的成员和其自身的对齐方法。有用对齐值N是终究用来决议数据寄存地址方法的值。有用对齐N,便是表明“对齐在N上”,也便是说该数据的”寄存开端地址%N=0″。而数据结构中的数据变量都是按界说的先后次序来排放的。榜首个数据变量的开端地址便是数据结构的开端地址。结构体的成员变量要对齐排放,结构体自身也要依据自身的有用对齐值圆整(结构体成员变量占用总长度需求是对结构体有用对齐值的整数倍)。下面结合VS2005中编译环境的比如进行深化了解:
比如B剖析:
struct B
{
char b;
int a;
short c;
};
假定B从地址空间0x0000开端排放。该例中没有显式指定对齐值N,VS2005默许值为4。
成员变量b自身对齐值是1,比指定或默许指定对齐值4小,故有用对齐值为1,其寄存地址0x0000契合0x0000%1=0,满意字节对齐准则。
成员变量a自身对齐值为4,和指定或默许指定对齐值4持平,故有用对齐值也为4,为了确保字节对齐,成员变量a只能寄存在开端地址为0x0004到0x0007这四个接连的字节空间中,复核0x0004%4=0。
成员变量c自身对齐值为2,比指定或默许指定对齐值4小,故有用对齐值为2,可次序寄存在0x0008至0x0009两个字节空间中,契合0x0008%2=0。
至此满意了数据成员的字节对齐,接着看数据结构B的对齐。数据结构B的自身对齐值为其变量中最大对齐值(也便是成员变量b)4,故结构体B的有用对齐值也是4。依据结构体圆整的要求, 0x0009到0x0000=10字节,(10+2)%4=0。所以0x0000A到0x000B也为结构体B所占用。故B从0x0000到0x000B 共有12个字节,sizeof(struct B)=12。
之所以在变量C弥补2字节,是由于要完成编译器快速有用的存取结构数组,试想假如界说B结构数组,榜首个结构开端地址是0没有问题,可是第二个结构呢?依照数组的界说,数组中一切元素都是紧挨着的,假如不把结构的巨细弥补为对齐值(4)的整数倍,那下一个结构的开端地址将是0x0000A,这明显不能满意结构的地址对齐了。
比如C剖析:

__align(2) struct C
{
char b;
int a;
short c;
};
同理,比如C中成员变量b自身对齐值为1,指定对齐值为2,故效对齐值为1,假定C从0x0000开端,那么b寄存在0x0000,契合0x0000%1= 0,满意字节对齐准则。
成员变量a自身对齐值为4,指定对齐值为2,故有用对齐值为2,次序寄存在0x0002、0x0003、0x0004、0x0005四个接连字节中,契合0x0002%2=0,满意字节对齐准则。
成员变量c的自身对齐值为2,与指定对齐值持平,故有用对齐值为2,次序寄存在0x0006、0x0007中,契合 0x0006%2=0,满意字节对齐准则。
从0x0000到0x00007共八字节寄存的是结构体C的变量。结构体C自身对齐值为4,比指定对齐值2大,故C的有用对齐值为2,因8%2=0,C只占用0x0000到0x0007的八个字节。所以sizeof(struct C)=8,彻底满意字节对齐准则。
除了指定的对齐值不同能导致数据结构的地址寄存不同外, 编译器不同寄存结构体方法也或许不同。

四、ARM渠道的对齐问题

在ARM中,有ARM和Thumb两种指令。

ARM指令:每履行一条指令,PC的值加4个字节(32bits).一次拜访4字节内容,该字节的开端地址有必要是4字节对齐的方位上,即地址的低两位为bits[0b00],也便是说地址有必要是4的倍数。

Thumb指令:每履行一条指令,PC的值加2个字节(16bits).).一次拜访2字节内容,该字节的开端地址有必要是2字节对齐的方位上,即地址的低两位为bits[0b0],也便是说地址有必要是2的倍数。

遵从以上方法叫对齐(aligned)方法,不恪守这样方法称为非对齐(unaligned)的存储拜访操作。

五、ARM渠道字节对齐关键字
1. __align(num)
用于修正第一流别目标的字节鸿沟。
A、在汇编中运用LDRD或许STRD时,就用到此指令__align(8)进行润饰约束。来确保数据目标是相应对齐。
B、该润饰目标的指令最大是8个字节约束,可让2字节的目标进行4字节
对齐,可是不能让4字节的目标2字节对齐。
C、 __align是存储类修正,他只润饰第一流类型目标不能用于结构或许函数目标。

2. __packed
__packed是进行一字节对齐。
A、不能对packed的目标进行对齐;
B、一切目标的读写拜访都进行非对齐拜访;
C、float及包括float的结构联合及未用__packed的目标将不能字节对齐;
D、__packed对部分整形变量无影响;
D、强制由unpacked目标向packed目标转化是未界说,整形指针能够合法定
义为packed __packed int* p; //__packed int 则没有意义。

3. __unaligned
用于润饰该变量可依照非对齐拜访。

六、怎么查找与字节对齐方面的问题
假如呈现对齐或许赋值问题首要检查:
1. 编译器的big little端设置;
2. 看这种系统自身是否支撑非对齐拜访;
3. 假如支撑看设置了对齐与否,假如没有则看拜访时需求加某些特别的润饰来标志其特别拜访操作。
七、定论
针关于32位处理器关于本地运用的数据结构,为进步内存拜访功率,选用四字节对齐方法;一起为了削减内存的开支,合理组织结构成员的方位,削减四字节对齐导致的成员之间的空地,下降内存开支。
关于处理器之间的数据结构,需求确保音讯的长度不由于在不同编译渠道和不同处理器导致音讯结构的长度发生变化,运用一字节对齐方法对音讯结构进行紧缩;为确保处理器之间的音讯的数据结构的内存拜访功率,选用字节填充的方法自己对音讯中成员进行四字节对齐。
数据结构的成员方位要统筹成员之间的联系、数据拜访功率和空间利用率。次序组织的准则是:四字节的放在最前面,两字节的紧接最终一个四字节成员,一字节紧接最终一个两字节成员,填充字节放在最终。举例如下:
typedef struct tag_T_MSG{
long ParaA;
long ParaB;
short ParaC;
char ParaD;
char Pad;
} T_MSG;

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/biancheng/257490.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部