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

Posted

技术标签:

【中文标题】将 xmm 寄存器推入堆栈时出错【英文标题】:errors when pushing xmm registers onto stack 【发布时间】:2015-03-18 01:56:56 【问题描述】:

我正在尝试使用 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,但无济于事,我不确定自己做错了什么。

提前致谢。

【问题讨论】:

你不能在不混淆编译器的情况下从内联汇编修改rsp。你也can't tell the compiler you're clobbering the red-zone, so you can't use the stack unless you skip the first 128b。如果您想在 inline-asm 中使用向量 reg,只需在其上声明一个 clobber,而不是自己保存/恢复它。 【参考方案1】:

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,而应使用Extended。那里的文档非常详细,并且有许多示例。

【讨论】:

以上是关于将 xmm 寄存器推入堆栈时出错的主要内容,如果未能解决你的问题,请参考以下文章

为啥将 32 位寄存器移动到堆栈然后从堆栈移动到 xmm 寄存器?

在函数调用之前保存 XMM 寄存器

将单个浮点数移动到 xmm 寄存器

如何将浮点常量值移动到xmm寄存器中?

如何将浮点常量值移动到 xmm 寄存器中?

将浮点数从高 xmm 四字移动到低 xmm 四字