(C中的内联汇编)有趣的内存分段故障

时间:2016-02-04 17:36:19

标签: c arrays assembly inline-assembly

我的 asm 汇编代码

中有以下部分
"LOOP%=:\n\t"
       "movapd  (%%eax), %%xmm4\n\t"
       "addl    $32, %%eax\n\t"
       "movsd   (%%edx), %%xmm5\n\t"
       "addl    $16, %%edx\n\t"
       "movapd  %%xmm4, %%xmm6\n\t"
       "subl    $1, %%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"循环索引"中,同时扫描两个(double *)数组A和B,使用SSE2执行某些计算。两个阵列都已对齐到64Bytes(与高速缓存行对齐,因此满足SSE的16Byte对齐要求)。 %eax持有"指针"数组A和" edx"持有一个"指针"到阵列B.它运行正常,没有内存读取错误。我想知道为什么要做

       "movapd  (%%eax), %%xmm4\n\t"
       "addl    $32, %%eax\n\t"
       "movsd  (%%edx), %%xmm5\n\t"
       "addl    $16, %%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    $1, %%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    $16, %%edx\n\t"
       "addpd   %%xmm6, %%xmm0\n\t"
       "movapd  16(%%eax), %%xmm6\n\t"
       "addl    $32, %%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"

但是我因无效读取而遇到分段错误。

这对我来说很有趣。为什么呢?

1 个答案:

答案 0 :(得分:2)

这是原因:

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

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