关于arm 的字节对齐
ARM中字节对齐的深入探讨
ARM中字节对齐的深入探讨
阅读了yos的文章《内存对齐问题学习小结》,深有体会,看来在进行指针操作时,必须进行强制类型转换,否则可能出现预想不到的错误。
在我的一个项目中,需要进行数据包解码,同样出现数据对齐的问题,却没能找到好的解决方法问题如下
CPU ARM7 ,编译环境 Keil RVCT3.0
#pragma pack(1)
typedef struct {
} TSTBLK,* PTSTBLK;
主程序
main
{
//以下语句是避免 u16k,u32m,u32l被优化掉
}
运行语句1 后, 结构体中的
u8a[] = 0x00~0x02
u8a[] = 0x03~0x06
u16c = 0x0807
u32d = 0x0C0B0A09
u32e = 0x100F0E0D
显然以上结果是我们所需要的,正确!
但继续运行 2,3,4得到
u16k = 0x0706
u32m = 0x080B0A09
u32l = 0x0C0F0E0D
字节对齐发生了问题,乱了!
乱得还不轻 u32m 没有等于0x0B0A0908
u32m 没有等于0x0B0A0908
u32m 也没有等于0x0F0E0D0C
why?
我试图用u16k = (uint16)(pTST->u16c);
去修改,但无效!
其实pTST->u16c本身就是16位的,强制转到16位自然没有任何意义。
你说的情况对于ARM CPU确实存在,但对于其它体系结构就不会出现
这是一个典型的ARM非对齐访问的问题。#pragma pack(1)能保证你的结构体中的数据是紧缩对齐的(在内存中是依次排列的)。那么对于
#pragma pack(1)
typedef struct {
} TSTBLK,* PTSTBLK;
假设该结构体存放的基地址为0,则u8a[3]位于0-2字节, u8b[4]位于3-6字节,u16c位于7-8字节,依次类推。那么当我们去访问u16c时编译器会编译成一条访问地址为7的半字读的汇编语言,而地址为7对于半字读来说是一个非对齐访问,CPU就自动会把地址变成把最低位忽略,也是说CPU读的实际地址为6,于是读u16c得到的是6 、7两个字节即u16c=0x0706。对于字的访问CPU会忽略低两位地址,分析方法与前相同。你的两个32位数我不能理解,你怎么可能得到那样的结果,是不是写错了哦??我觉得你应该分别得到0x0B0A0908 0x0F0E0D0C才对。当然还涉及一个字节序的问题。
这一个问题在ARM CPU中会出现,但对于POWERPC的CPU或X86的CPU你的代码就不会出现问题,这都是CPU对非对齐访问采用的处理方式不同造成,POWERPC X86 会把非半字的非对齐访问变成两个字节访问,因为不会出现上面问题。MIPS我没有去研究过。
对于ARM CPU把结构体改为:
#pragma pack(1)
typedef struct {
uint16 u16c;
uint8 u8a[3];
} TSTBLK,* PTSTBLK;
整个结构体仍然只占23个字节,但应该不会出现前面的问题。
谢谢大家,用__packed 可以解决问题,但我没理解__packed 和#pragma pack(1)的区别,请问谁能再解释得清楚些?
我先前的实验结果确实是 u32m = 0x080B0A09
为什么不是0x0B0A0908 和0x0F0E0D0C,原因不详
我不同意更改结构体,因为数据结构是规定死了,不能随意改
对于ARM CPU把结构体改为:
#pragma pack(1)
typedef struct {
uint16 u16c;
uint8 u8a[3];
} TSTBLK,* PTSTBLK;
uboot中,ARM体系下,设置变量4字节对齐
调试程序遇到由于buffer地址不是4字节对齐,所有底层去:
u32 *p =(u32 *)buf;
使得数据拷贝有误。所以,去参考了uboot中其他人的做法:
\board\s1845\flash.c中的:
#define __align__ __attribute__ ((aligned (8)))
static __align__ ulong precmd0[2]
所以,此处就可以这么做,使一个字符数组变量4字节对齐的:
static__attribute__ ((aligned (4)))unsigned char data_buf[MAX_PAGE_SIZE];
ARM 的 RealView中的解释:
4.4.2.__attribute__((aligned))
aligned类型属性指定类型的最低对齐要求。
Note
此类型属性是 ARM 编译器支持的 GNU 编译器扩展。
| Copyright 2007-2009 ARM Limited. All rights reserved. | ARM DUI 0348BC |
| Non-Confidential, Unrestricted Access |
4.5.3 __attribute__((aligned))
aligned 变量属性指定变量或结构字段的最低对齐要求(按字节计算)。
注意
此变量属性是 ARM 编译器支持的 GNU 编译器扩展。
示例
int Variable_Attributes_aligned_0 __attribute__ ((aligned (16)));
short Variable_Attributes_aligned_1[3] __attribute__ ((aligned));
arm字节对 相关文章:
- ARM字节对齐问题详解(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
