Log*_*ing 2 arm g++ memory-alignment arm64
我使用 linaro g++ for ARM arch64 编译一个简单的 cpp 文件:
int main()
{
char *helloMain = "main module (crm.c)";
long faculty, num = 12;
int stop,mainLoop = 1;
char word[80] = "";
}
Run Code Online (Sandbox Code Playgroud)
objdump生成elf文件后,我得到了它的asm代码:
0000000000001270 <main>:
int main()
{
1270: d101c3ff sub sp, sp, #0x70
char *helloMain = "main module (crm.c)";
1274: 90000020 adrp x0, 5000 <_malloc_trim_r+0x160>
1278: 9111c000 add x0, x0, #0x470
127c: f90003e0 str x0, [sp]
long faculty, num = 12;
1280: d2800180 movz x0, #0xc
1284: f90007e0 str x0, [sp,#8]
int stop,mainLoop = 1;
1288: 52800020 movz w0, #0x1
128c: b90013e0 str w0, [sp,#16]
char word[80] = "";
1290: 910063e0 add x0, sp, #0x18
1294: 90000021 adrp x1, 5000 <_malloc_trim_r+0x160>
1298: 91122021 add x1, x1, #0x488
129c: 39400021 ldrb w1, [x1]
12a0: 39000001 strb w1, [x0]
12a4: 91000400 add x0, x0, #0x1
12a8: a9007c1f stp xzr, xzr, [x0]
12ac: a9017c1f stp xzr, xzr, [x0,#16]
12b0: a9027c1f stp xzr, xzr, [x0,#32]
12b4: a9037c1f stp xzr, xzr, [x0,#48]
12b8: f900201f str xzr, [x0,#64]
12bc: b900481f str wzr, [x0,#72]
12c0: 7900981f strh wzr, [x0,#76]
12c4: 3901381f strb wzr, [x0,#78]
}
12c8: 52800000 movz w0, #0x0
12cc: 9101c3ff add sp, sp, #0x70
12d0: d65f03c0 ret
Run Code Online (Sandbox Code Playgroud)
在 ARMV8 板上执行此代码之前,sp将其初始化为与 0x1000 对齐的地址。
执行此类代码会在 12a8 上引发对齐错误异常:a9007c1f stp xzr, xzr, [x0]
我注意到x0添加了,因此它与执行指令时0x1对齐。0x1stp
为什么g++没有使其对齐0x10以避免这种对齐错误异常?
g++ 版本是:
gcc 4.8.1 20130506 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2013.05 - Linaro GCC 2013.05)
Run Code Online (Sandbox Code Playgroud)
从手册中:
-munaligned-access
-mno-unaligned-access启用(或禁用)从非 16 位或 32 位对齐的地址读取和写入 16 位和 32 位值。默认情况下,对于所有 ARMv6 之前的架构和所有 ARMv6-M 架构,未对齐访问处于禁用状态,而对于所有其他架构,未对齐访问处于启用状态。如果未启用未对齐访问,则打包数据结构中的字将一次访问一个字节。
ARM 属性 Tag_CPU_unaligned_access 将在生成的目标文件中设置为 true 或 false,具体取决于此选项的设置。如果启用了未对齐访问,则还将定义预处理器符号 __ARM_FEATURE_UNALIGNED。
AArch64/ARMv8 支持开箱即用的未对齐访问,因此 GCC 假设它可用。如果不是这种情况,您可能必须使用上述开关显式禁用它。您使用的“预发布”版本也可能尚未完成,并且存在各种错误/问题。
编辑
正如评论中提到的,相应的AArch64选项是:
-mstrict-align
-mno-strict-align避免或允许生成可能与体系结构规范中描述的自然对象边界不对齐的内存访问。
顺便说一句,代码的行为如下,因为 GCC 按字面解释了赋值:
我怀疑如果启用优化,未对齐的访问将会消失。或者,如果您使用char word[80] = {0},它应该一次性完成归零。