【问题标题】:Eclipse C++: How do I insert inline assembly code?Eclipse C++:如何插入内联汇编代码?
【发布时间】:2015-02-21 16:40:27
【问题描述】:

我有一个 C++ 项目,我想在汇编中插入代码块。 我可以使用哪些解决方案? 我使用g ++和我的cpu的编译器是i5。

到目前为止我尝试过:

void f1(int a){
    asm(
        "mov edx,4"
    );
}
............

编译时出现此错误:

error: unknown use of instruction mnemonic without a size suffix

我尝试了更多在 google 上找到的示例,但每个示例都给出了不同的错误。

EDIT2:

void f1(int a) {
    int r = 0;
    cout << "start";
    __asm__(
            "movl %edx,4;"
    );
    cout << r;
    cout << a;
    cout << "end";
}

int main(){
    f1(2);
    return 1;
}

构建成功但输出为空...不打印任何内容...但是如果删除 __asm_(..),则输出如下:“start02end”...为什么使用 asm 块不什么都不打印??

【问题讨论】:

  • 这个问题似乎是题外话,因为 OP 肯定甚至没有尝试阅读任何文档。
  • 试试 AT&T 语法,但你可能不会喜欢它。您也可以使用 YASM 或其他任何东西并单独组装一些代码,然后将其链接。
  • gcc 内联汇编是一件复杂的事情。去阅读documentation,如果你有更具体的问题再回来。除了使用单独的 asm 模块之外,您还可以考虑内置矢量支持和内在函数(您没有说您想用 asm 代码做什么)。 PS:你可以使用-masm=intel切换到intel语法。

标签: assembly x86 g++ inline-assembly


【解决方案1】:

gcc 内联汇编是一件复杂的事情。去阅读documentation了解详情。即使它看起来正在工作,它也可能在不同的情况下神秘地失败。你真的需要知道你在做什么。

也就是说,这里有一个快速概述:gcc 根本不解析您的 asm 块,它认为它是一个黑匣子。您需要根据它期望什么输入、它提供什么输出以及它破坏什么状态来描述它。

您将 4 加载到 edx 的示例毫无意义,您只是在不知道编译器使用该寄存器的情况下覆盖了一个寄存器。您不能期望该代码有任何特定的结果。此外,您的 at&t 转换 (movl %edx, 4) 是错误的,因为 at&t 期望操作数以相反的顺序排列,而立即数需要 $ 前缀。因此,您的代码会将edx 的内容写入内存位置4,这将出现段错误。

一个有效(但仍然没有意义)的例子是:

__asm__("movl $4, %%edx" : : : "edx");

这会将4 加载到edx 中,同时还告诉编译器您破坏了edx 的先前值。该指令将包含在生成的程序中,但由于没有使用 edx 并且 asm 块没有输出,因此它不会产生任何影响。

在您的示例中插入了一个更有趣的示例:

void f1(int a) {
    int r = 0;
    cout << "start";
    __asm__("addl $1, %0" : "+d" (a));
    cout << r;
    cout << a;
    cout << "end";
}

这将要求编译器将a 的值放入寄存器edx(由d 约束字母表示),然后将%edx 替换为%0 的asm 块(指操作数0 ) 最后从%edx 再次写回a+ 修饰符表示一个读写操作数。因此,此代码将打印start03end

正如 cmets 中所说,确保您确实需要内联汇编,并且不能使用矢量支持、内在函数或单独的汇编模块。

【讨论】:

  • d 仅用于约束,clobber 列表使用完整的寄存器名称。
猜你喜欢
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 2019-11-30
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 2021-01-19
相关资源
最近更新 更多