我在我的代码中检测到一个奇怪的分段错误,如果这可能是GCC错误,还是我的错,我想听听您的意见!
该函数如下所示:
void testMMX( ... ) {
unsigned long a = ...;
unsigned char const* b = ...;
unsigned long c = ...;
__asm__ volatile (
"pusha;"
);
__asm__ volatile ( "mov %0, %%eax;" : : "m"( a ) : "%eax" ); // with "r"( a ) it just works fine!
__asm__ volatile ( "add %0, %%eax;" : : "m"( b ) : "%eax" );
__asm__ volatile ( "mov %0, %%esi;" : : "m"( c ) : "%eax", "%esi" );
__asm__ volatile (
"sub %eax, %esi;"
"dec %esi;"
"movd (%esi), %mm0;"
"popa;"
);
}
如果我使用-O0进行编译,则效果很好.但是它使用-O1和-O2进行SegFaults.我花了很长时间才弄清楚此段错误是由帧指针遗漏引起的. pusha指令将堆栈大小增加4 * 8 = 32字节(x86_32),因此ESP也应增加.但是gcc无法识别这一点.如果我手动添加ESP修复程序
__asm__("add $32, %esp")
或在gcc中使用“ -fno-omit-frame-pointer”标志,我可以使用-O1和-O2进行编译和运行,而不会出现任何错误!
所以我现在的问题是:如果启用了帧指针省略功能,为什么gcc不能通过任何push / pop内联汇编程序来调整ESP?这是gcc错误吗? gcc甚至能够检测到这一点吗?我想念什么吗?
解决这个问题将非常有趣.
提前致谢!
解决方法:
否-gcc无法检测到这一点.它不对asm块中出现的指令进行任何分析.您有责任将任何副作用通知编译器.您能解释一下您正在执行的测试吗?
另外,您应该考虑为该代码使用单个asm块; volatile可能会阻止对asm块进行重新排序,但是您会选择cannot assume this yields consecutive instructions.