(C 中的内联汇编)有趣的内存分段错误

(inline assembly in C) Funny memory segmentation fault

我的 asm 汇编代码中有以下部分

"LOOP%=:\n\t"
       "movapd  (%%eax), %%xmm4\n\t"
       "addl    , %%eax\n\t"
       "movsd   (%%edx), %%xmm5\n\t"
       "addl    , %%edx\n\t"
       "movapd  %%xmm4, %%xmm6\n\t"
       "subl    , %%ecx\n\t"
       "unpcklpd %%xmm5, %%xmm5\n\t"
       "testl   %%ecx, %%ecx\n\t"
       "mulpd   %%xmm5, %%xmm6\n\t"
       "movsd   -8(%%edx), %%xmm7\n\t"
       "addpd   %%xmm6, %%xmm0\n\t"
       "movapd  -16(%%eax), %%xmm6\n\t"
       "unpcklpd %%xmm7, %%xmm7\n\t"
       "mulpd   %%xmm6, %%xmm5\n\t"
       "addpd   %%xmm5, %%xmm1\n\t"
       "mulpd   %%xmm7, %%xmm4\n\t"
       "addpd   %%xmm4, %%xmm2\n\t"
       "mulpd   %%xmm6, %%xmm7\n\t"
       "addpd   %%xmm7, %%xmm3\n\t"
       "jne LOOP%=\n\t" */

此代码保存在 %ecx a "loop index" 中,同时扫描两个(双 *)数组 A 和 B 使用 SSE2 执行一些计算。两个数组都已对齐到 64 字节(对齐到高速缓存行,因此满足 SSE 的 16 字节对齐要求)。 %eax对数组A持有一个"pointer","edx"对数组B持有一个"pointer",运行正常,没有内存读取错误。我想知道为什么我必须这样做

       "movapd  (%%eax), %%xmm4\n\t"
       "addl    , %%eax\n\t"
       "movsd  (%%edx), %%xmm5\n\t"
       "addl    , %%edx\n\t"
       ......
       "movsd   -8(%%edx), %%xmm7\n\t"
       ......
       "movapd  -16(%%eax), %%xmm6\n\t"
       ......

所以我将初始版本更改为

   "LOOP%=:\n\t"
       "movapd  (%%eax), %%xmm4\n\t"
       "movsd   (%%edx), %%xmm5\n\t"
       "movapd  %%xmm4, %%xmm6\n\t"
       "subl    , %%ecx\n\t"
       "unpcklpd %%xmm5, %%xmm5\n\t"
       "testl   %%ecx, %%ecx\n\t"
       "mulpd   %%xmm5, %%xmm6\n\t"
       "movsd   8(%%edx), %%xmm7\n\t"
       "addl    , %%edx\n\t"
       "addpd   %%xmm6, %%xmm0\n\t"
       "movapd  16(%%eax), %%xmm6\n\t"
       "addl    , %%eax\n\t"
       "unpcklpd %%xmm7, %%xmm7\n\t"
       "mulpd   %%xmm6, %%xmm5\n\t"
       "addpd   %%xmm5, %%xmm1\n\t"
       "mulpd   %%xmm7, %%xmm4\n\t"
       "addpd   %%xmm4, %%xmm2\n\t"
       "mulpd   %%xmm6, %%xmm7\n\t"
       "addpd   %%xmm7, %%xmm3\n\t"
       "jne LOOP%=\n\t"

但后来我遇到了无效读取的分段错误。

我觉得很有趣。为什么?

这是原因:

   "testl   %%ecx, %%ecx\n\t"

此测试的结果用于此代码最后的循环条件中。随着添加操作的移动,您可以覆盖条件的标志,因此它始终得到满足并永远运行直到离开内存。