|
发表于 2009-8-28 16:41:07
|
显示全部楼层
最近在看arm调试与优化这本书的时候,看到作者强调边界不对齐和字节排序的问题,这个问题以前老师也
提到过,没引起重视,这次上网查查,又在keil上走了一遍,发现还真有问题,如下:
char buff[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, 0xbc, 0xcd};
int v32, *p32;
short v16, *p16;
p32 = (int*)&( buff[1] ); //unalignment
p16 = (short*)&( buff[1] ); //unalignment
v32 = *p32; //what’s the result?
v16 = *p16; //what’s the result?
在keil上得到的结果是:
v32 = 0x9a785634
v16 = 0x5634
分析原因:由于buffer中的数据是字节排列的,在keil中buffer的起始地址为:
2 (原文件名:2.jpg)
可见,起始地址最低位为:0b1100,汇编伪指令为:
9: p32 = (int*)&( buff[1] ); //unalignment
0x000001C4 E28D2001 ADD R2,R13,#0x00000001
10: p16 = (short*)&( buff[1] ); //unalignment
0x000001C8 E28DC001 ADD R12,R13,#0x00000001
11: v32 = *p32;
0x000001CC E5921000 LDR R1,[R2]
12: v16 = *p16;
0x000001D0 E1DC30F0 LDRSH R3,[R12]
在第11行LDR R1,[R2]中R2的地址为0b1101,此时为非对齐地址,LDR从一个非对齐地址得到一个字数据,会导致取数据错误!
同理对于16位数据的取出也会造成错误。如何解决这个问题,在对速度要求不是很严格的地方,可以编写两个函数,解决从边界可能不对其的存储器中取出4字节或2字节数据的问题。
函数如下:
int byte_to_word(char *data)
{
int a0,a1,a2,a3;
a0=*(data++);
a1=*(data++);
a2=*(data++);
a3=*(data++);
return a0|(a1<<8)|(a2<<16)|(a3<<24);
}
int byte_to_halfword(char *data)
{
int a0,a1;
a0=*(data++);
a1=*(data++);
return a0|(a1<<8);
}
此时再测试:
char buff[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, 0xbc, 0xcd};
int v32, *p32;
short v16, *p16;
v32 = byte_to_word(&buff[1]); //unalignment
v16 = byte_to_halfword(&buff[1]); //unalignment
得到了正确的数据:
3 (原文件名:2.jpg)
这个是我通过实验得到的结论 |
|