- 论坛徽章:
- 2
|
"老大"这个帽子还是不怎么适合我,呵 
我个人认为 对齐需要分两种,一种是处理器的对齐,一种是编译器的对齐。
处理器对齐 在arm上意味着byte必须以8bit对齐,int32必须以32bit对齐。而在x86上,由于CISC处理器特性,它支持十分复杂的存储器操作,这一点从支持的多达10多种 寻址方式上就可以体会出来。因此x86上即使int32也可以按照8bit对齐,只不过损失的是访问效率。
编译器对齐 意味着编译器选择自己喜欢的方式来完成多起操作。如果不能处理器对齐,那么编译器会选择自己喜欢的方式处理。
以arm为例:
下面是你的简短代码
- #pragma pack(1)
- struct xxx {
- char a;
- long b;
- short c;
- };
- int
- main()
- {
- struct xxx m;
- m.a = 'a';
- m.b = 12;
- m.c = 23;
- return sizeof(struct xxx);
- }
复制代码
首先看默认的平台,编译器如何处理
vi[~]# arm--netbsdelf-gcc -S mmm.c -o mmm.S
mov r3, #97
strb r3, [fp, #-19]
mov r3, #0
orr r3, r3, #12
strb r3, [fp, #-18]
mov r3, #0
strb r3, [fp, #-17]
mov r3, #0
strb r3, [fp, #-16]
mov r3, #0
strb r3, [fp, #-15]
mov r3, #0
orr r3, r3, #23
strb r3, [fp, #-14]
mov r3, #0
strb r3, [fp, #-13]
mov r3, #7
mov r0, r3
这里十分明显,这里不能够依赖处理器对齐,因此编译器完全把所有元素都按照strb来处理,效率低下不是一般。但是,sizeof的结果,是7。
将编译参数增加为: arm--netbsdelf-gcc -march=armv4 -S mmm.c -o mmm.S
你可以自己看一下,编译器仍然将所有元素按照strb处理。
如果去掉#pragma pack(1)
仍然使用默认选项编译,结果是
mov r3, #97
strb r3, [fp, #-24]
mov r3, #12
str r3, [fp, #-20]
mov r3, #23
mov r2, #0
strb r3, [fp, #-16]
strb r2, [fp, #-15]
mov r3, #12
mov r0, r3
当然,sizeof是12,但是最后的short不支持直接操作,编译器帮你换成strb操作。
添加-mach=armv4
mov r3, #97
strb r3, [fp, #-24]
mov r3, #12
str r3, [fp, #-20]
mov r3, #23
strh r3, [fp, #-16] @ movhi
mov r3, #12
mov r0, r3
呵呵,新平台,当然就有strh了。 |
|