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

我的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中保存“循环索引”,同时扫描两个(double *)数组A和B,使用SSE2执行某些计算。 两个arrays都已对齐到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" 

但后来我因无效读取而遭受分段错误。

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

这是原因:

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

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