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