ARM下的对齐处理

from DUI0067D_ADS1_2_CompLib

3.13 type  qulifiers

有部分摘自ARM编译器文档对齐部分

对齐的使用:
1.__align(num)
   这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时
   就要用到此命令__align(8)进行修饰限制。来保证数据对象是相应对齐。
   这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节
   对齐,但是不能让4字节的对象2字节对齐。
   __align是存储类修改,他只修饰最高级类型对象不能用于结构或者函数对象。
  
2.__packed
  __packed是进行一字节对齐
  1.不能对packed的对象进行对齐
  2.所有对象的读写访问都进行非对齐访问
  3.float及包含float的结构联合及未用__packed的对象将不能字节对齐
  4.__packed对局部整形变量无影响
  5.强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定
  义为packed。
     __packed int* p;  //__packed int 则没有意义
  6.对齐或非对齐读写访问带来问题
  __packed struct STRUCT_TEST
 {
  char a;
  int b;
  char c;
 }  ;    //定义如下结构此时b的起始地址一定是不对齐的
         //在栈中访问b可能有问题,因为栈上数据肯定是对齐访问[from CL]
//将下面变量定义成全局静态不在栈上
static char* p;
static struct STRUCT_TEST a;
void Main()
{
 __packed int* q;  //此时定义成__packed来修饰当前q指向为非对齐的数据地址下面的访问则可以

 p = (char*)&a;         
 q = (int*)(p+1);     
 
 *q = 0x87654321; 
/*  
得到赋值的汇编指令很清楚
ldr      r5,0x20001590 ; = #0x12345678
[0xe1a00005]   mov      r0,r5
[0xeb0000b0]   bl       __rt_uwrite4  //在此处调用一个写4byte的操作函数
      
[0xe5c10000]   strb     r0,[r1,#0]   //函数进行4次strb操作然后返回保证了数据正确的访问
[0xe1a02420]   mov      r2,r0,lsr #8
[0xe5c12001]   strb     r2,[r1,#1]
[0xe1a02820]   mov      r2,r0,lsr #16
[0xe5c12002]   strb     r2,[r1,#2]
[0xe1a02c20]   mov      r2,r0,lsr #24
[0xe5c12003]   strb     r2,[r1,#3]
[0xe1a0f00e]   mov      pc,r14
*/

/*
如果q没有加__packed修饰则汇编出来指令是这样直接会导致奇地址处访问失败
[0xe59f2018]   ldr      r2,0x20001594 ; = #0x87654321
[0xe5812000]   str      r2,[r1,#0]
*/

//这样可以很清楚的看到非对齐访问是如何产生错误的
//以及如何消除非对齐访问带来问题
//也可以看到非对齐访问和对齐访问的指令差异导致效率问题
}
 
 
    

你可能感兴趣的:(c,汇编,struct,float,byte,编译器)