我正在使用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] = "";
}
在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
在ARMV8板上执行此代码之前,sp
初始化为与0x1000对齐的地址。
执行此类代码会引发对齐错误异常 12a8:a9007c1f stp xzr,xzr,[x0]
我注意到x0
添加了0x1
,因此在执行0x1
指令时它与stp
对齐。
为什么g ++没有与0x10
对齐以避免这种对齐错误异常?
g ++版本是:
gcc 4.8.1 20130506 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2013.05 - Linaro GCC 2013.05)
答案 0 :(得分:2)
来自the manual:
-munaligned-access
-mno-unaligned-access
启用(或禁用)从非16位或32位对齐的地址读取和写入16位和32位值。 默认情况下,对所有pre-ARMv6及所有ARMv6禁用未对齐访问 ARMv6-M架构,并为所有其他架构启用 。如果 未打开未对齐的访问权限,然后打包数据结构中的单词 将一次访问一个字节。
将在中设置ARM属性Tag_CPU_unaligned_access 生成的对象文件为true或false,具体取决于 设置此选项。如果启用了未对齐访问,则启用 预定义符号__ARM_FEATURE_UNALIGNED也将被定义。
AArch64 / ARMv8支持开箱即用的未对齐访问,因此GCC认为它可用。如果不是这种情况,您可能必须使用上述开关明确禁用它。你正在使用的“预发布”版本也可能尚未完成,并且存在各种错误/问题。
顺便说一下,代码的行为是这样的,因为GCC按字面解释了赋值:
我怀疑如果你启用了优化,那么未对齐的访问将会消失。
或者,如果您使用char word[80] = {0}
,它应该一次性进行归零。
答案 1 :(得分:2)
在对ARMV8架构进行一些研究之后,我对我遇到的数据中止异常有了更深入的了解。
为什么会出现这种对齐故障异常?
正如@IgorSkochinsky所提到的,AArch64 / ARMv8支持不对齐访问。但是当我在一个简单的裸机环境中工作时,MMU没有被接受,所以在这种情况下,内存被视为设备,设备不支持未对齐访问。如果启用了MMU,则此异常消失。
如何强制GCC编译未对齐访问的免费精灵文件?
从手册中,-mno-unaligned-access
应该足够了,但对于我的GCC版本:
gcc 4.8.1 20130506(预发布)(crosstool-NG linaro-1.13.1-4.8-2013.05 - Linaro GCC 2013.05)
它说没有这样的选择。就我而言,另一个选项-mstrict-align
解决了这个问题。