系统相关
首页 > 系统相关> > linux-使用-O1和内联汇编程序的GCC分段错误

linux-使用-O1和内联汇编程序的GCC分段错误

作者:互联网

我在我的代码中检测到一个奇怪的分段错误,如果这可能是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.

标签:debugging,gcc,ubuntu,inline-assembly,linux
来源: https://codeday.me/bug/20191029/1963865.html