gcc inline asm 跳转到带有交叉抛出异常的标签

Posted

技术标签:

【中文标题】gcc inline asm 跳转到带有交叉抛出异常的标签【英文标题】:gcc inline asm jump to a label with crossing throwing an exception 【发布时间】:2013-09-18 03:04:50 【问题描述】:

我想添加两个int 号码。如果溢出,抛出异常。 当我抛出异常时,代码无法编译。但如果我不写其他代码也没关系。

#include <iostream>
#include <stdexcept>

int main()

    int a,b;
    std::cin >> a >> b;
    asm("movl %0, %%eax;\n\t"
        "addl %1, %%eax\n\t"
        "jno _L_NO_OVERFLOW_\n\t;"
        :
        :"m"(a),"m"(b)
        :"%eax");
    throw std::overflow_error("overflow");
    //std::cout << "overflow" << std::endl;//it's OK
    asm("_L_NO_OVERFLOW_:\n\t"
        "movl %%eax, %0\n\t"
        :"=m"(a));
    std::cout << a << std::endl;
    return 0;

错误信息是undefined reference to L_NO_OVERFLOW_

【问题讨论】:

也许你的编译器认为asm 在你的代码不可访问且未编译之后阻塞。尝试在asm之前写volatile 易变死代码仍是淘汰对象 【参考方案1】:

你必须使用asm goto表单来指定标签:

#include <iostream>
#include <stdexcept>

int main()

    int a,b;
    std::cin >> a >> b;
    asm goto ("movl %0, %%eax;\n\t"
              "addl %1, %%eax\n\t"
              "jno %l2\n\t;"
              :
              :"m"(a),"m"(b)
              :"%eax"
              :L_NO_OVERFLOW);

    throw std::overflow_error("overflow");

    L_NO_OVERFLOW:
    asm("movl %%eax, %0\n\t"
        :"=m"(a));
    std::cout << a << std::endl;
    return 0;

想法是告诉编译器,您的内联汇编器破坏标签,并直接指定涉及该标签的控制流。

UPD:还请注意,您必须拥有相当新的 gcc 才能支持此功能。版本 > 4.5 似乎没问题。我在 4.8.1 上测试过

【讨论】:

做得很好。另外,我想知道为什么使用std::cout... 是可以的。 它不会在控制流中创建障碍,并且下一个 asm 不是死代码。

以上是关于gcc inline asm 跳转到带有交叉抛出异常的标签的主要内容,如果未能解决你的问题,请参考以下文章

gcc inline asm 不编译

GCC 内联汇编中的标签

movl on x64 with GCC inline

翻译 | “扩展asm”——用C表示操作数的汇编程序指令

交叉编译:特殊的交叉编译器或只是带有选项 -march 的 gcc?

编程式路由跳转到当前路由, 控制台抛出NavigationDuplicated的错误