我有一个用 64 位 x86 程序集(gcc 和 GAS 的 AT&T 语法)编写的函数,它执行一些 SSE2 操作。我已经通过使用带有反汇编的 gdb 并查看寄存器值来检查结果,所以我知道它产生了正确的结果。在 retq 指令之后,我得到一个分段错误。由于我是汇编新手(并且从未上过任何课程),我猜我没有正确处理函数/主程序接口。该函数接受 2 个指针和一个 int,并预计返回一个浮点数。这就是我在汇编函数中处理输入/输出的方式:
float foo(float *x,float *y,unsigned int s)
{
__asm__ __volatile__(
"movl -0x14(%%rbp),%%ecx \n\t" //ecx = s
"movq -0x8(%%rbp),%%rax \n\t" //rax -> x
"movq -0x10(%%rbp),%%rdx \n\t" //rdx -> y
"subq $4,%%rsp \n\t" //function result
#sse2 operations that end up with the answer in xmm4...
"movss %%xmm4,(%%rsp) \n\t" //store result
"flds (%%rsp) \n\t" //load function result
"addq $4,%%rsp \n\t" //adjust stack
"ret \n\t"
:
:"g"(s)
:"%ecx","%rax","%rdx"
);
}
这是似乎导致段错误的行(这是反汇编中 ret 之后的指令):
0x00007fffffffe0d0 in ?? ()
=> 0x00007fffffffe0d0: 00 00 add %al,(%rax)
我不知道为什么它在执行我的函数后将 rax 的低位中的值添加回 rax,但它似乎正在崩溃。我是否不允许在我的汇编函数中使用 rax,即使它是通用的并且我声明它已被破坏?
我不确定您是否需要查看这部分,但这是 gcc 期望处理该功能的方式;我已经包含了调用我的函数的行的反汇编:
#asm dealing with function inputs
callq 0x400520 <foo>
movss %xmm0,-0x48(%rbp)
mov -0x48(%rbp),%eax
mov %eax,-0x34(%rbp)
这就引出了我的第二个问题,为什么将 xmm0 中的值任意移动到两个位置?我是否应该让我的函数以 xmm0 的结果结束,或者这是否意味着我应该避免使用 xmm0?我很困惑,不胜感激。提前感谢任何花时间阅读我的菜鸟帖子的人:)