【发布时间】:2021-12-27 21:22:02
【问题描述】:
在 x86-64 上使用 AT&T 语法,我希望将 c = a + b; 组装为
add %[a], %[b], %[c]
不幸的是,GNU 的汇编器不会这样做。为什么不呢?
详情
根据英特尔的软件开发人员手册, rev. 75(2021 年 6 月),卷。 2,第 2.5 节,
VEX 编码的通用寄存器指令具有...对三个可编码操作数的指令语法支持。
VEX 前缀是 AVX 功能,因此从 Sandy Bridge/Bulldozer 开始的 x86-64 CPU 实现了它。那是十年前的事了,所以 GNU 的汇编器应该汇编我的三操作数指令,不是吗?
为了澄清,我知道可以用旧样式写成
mov %[a], %[c]
add %[b], %[c]
但是,我希望以新的 VEX 风格编写它。顺便说一句,我通过向 GCC 发出 -march=skylake 命令行选项来通知汇编器我有一个现代 CPU。
请问我的错误是什么?
示例代码
在 C++ 包装器中,
#include <cstddef>
#include <iostream>
int main()
{
volatile int a{8};
volatile int b{5};
volatile int c{0};
//c = a + b;
asm volatile (
//"mov %[a], %[c]\n\t"
//"add %[b], %[c]\n\t"
"add %[a], %[b], %[c]\n\t"
: [c] "=&r" (c)
: [a] "r" (a), [b] "r" (b)
: "cc"
);
std::cout << c << "\n";
}
【问题讨论】:
-
回答您的问题,您是否尝试过使用 lea 指令?
-
@fuz 不。这是一个很好的观点,因为它解释了为什么英特尔和 AMD 不会费心为
add指令实现 VEX。有人怀疑未来的访客会发现您的观察很有帮助;那么,当您有时间时,您愿意将其添加为正确的答案吗? -
我认为您在这里有某种误解。 VEX 前缀不适用于 AVX/AVX2 之外的现有指令。所有带有 VEX 前缀的标量指令都是全新的,带有新的操作码。通常的添加指令(操作码
00到03)甚至不能进行 VEX 编码,因为 VEX 编码具有这些指令所缺少的隐式0f、0f 38或0f 3a前缀。您不能只接受任何随机指令并对其应用 VEX 前缀。这不是它的工作原理。
标签: assembly x86-64 avx gnu-assembler