将 xmm 寄存器压入堆栈时出错

errors when pushing xmm registers onto stack

我正在尝试使用 GCC 样式的内联汇编在 x86_64 C 代码中将 xmm 寄存器压入堆栈。我查看了 this 问题的答案并正在使用此代码

int main(void) {
    asm volatile("subq 16, %rsp");
    asm volatile("movdqu xmm0, xmmword ptr (%rsp)");
}

当我在 OS X 10.10.2 上用 clang 6.0 编译它时,我收到错误 error: unexpected token in argument list,并且在第二个 asm 行中有一个绿色箭头指向 ptr。

我把代码改成

int main(void) {
    asm volatile("subq 16, %rsp");
    asm volatile("movdqu xmm0, xmmword (%rsp)");
}

它给了我 error: invalid operand for instruction。我已经尝试将 xmmword 更改为 dqword,但没有用,而且我不确定自己做错了什么。

提前致谢。

x86 有(至少)两种汇编语言:intel 格式和 at&t 格式。看起来你正在尝试使用 intel 格式编写代码,但使用 at&t 进行编译。

您的代码将编译为:

int main(void) {
    asm volatile("subq 16, %rsp");
    asm volatile("movdqu %xmm0, (%rsp)");
}

如果你使用了 -masm=intel 编译开关,你也可以使用这个(你可能看起来更熟悉):

int main(void) {
    asm volatile("sub rsp, 16");
    asm volatile("movdqu xmmword ptr [rsp], xmm0");
}

也就是说,像这样使用多个 asm 语句编写 asm 块是个坏主意。 gcc 文档明确 state:

不要期望一系列 asm 语句在编译后保持完美连续。如果某些指令需要在输出中保持连续,请将它们放在单个多指令 asm 语句中。

所以也许更像是:

int main(void) {
    asm volatile("subq 16, %rsp\n"
                 "movdqu %xmm0, (%rsp)");
}

此外,如果您要读取或更新变量,则不应使用 basic asm, but instead use Extended。那里的文档非常详细,并且有很多示例。