扩展内联汇编 gcc - 计算二次公式根

Posted

技术标签:

【中文标题】扩展内联汇编 gcc - 计算二次公式根【英文标题】:Extended inline assembly gcc - Calculating Quadratic Formula roots 【发布时间】:2015-03-06 06:19:15 【问题描述】:

我正在编写一个程序,使用 gcc 扩展的内联汇编代码来编写一个计算二次根(来自二次公式)的程序。我已经编写了所有代码,并且一直遇到以下错误:

“无效的'asm':%-字母后缺少操作数”

当我尝试编译我的程序时,我收到此错误 7 次。我的主要问题是:这是什么意思,为什么会这样?这是一个家庭作业,所以我本身并不是在寻求解决方案,但我只是无法弄清楚该错误消息在我的代码适用于哪些部分方面意味着什么(变量,我在想现在?)

这是我的代码:

#include <stdio.h>

#include <stdlib.h>

#include <math.h>


// function for checking that your assembly code is computing the correct result


double quadraticRootC(double a, double b, double c)



        return (-b + sqrt(b * b - 4 * a * c)) / (2 * a);




double quadraticRoot(double a, double b, double c)



// write assembly code below to calculate the quadratic root

        double root;

        asm(
                "fld        %a              \n"
                "fadd       %%ST            \n"
                "fld        %a              \n"
                "fld        %c              \n"
                "fmulp      %%ST(1)         \n"
                "fadd       %%ST            \n"
                "fadd       %%ST            \n"
                "fchs                       \n"
                "fld        %b              \n"
                "fld        %b              \n"
                "fmulp      %%ST(1)         \n"
                "faddp      %%ST(1)         \n"
                "ftst                       \n"
                "fstsw      %%AX            \n"
                "sahf                       \n"
                "fsqrt                      \n"
                "fld        %b              \n"
                "fchs                       \n"
                "fdivp      %%ST(1)         \n"
                "mov        %root, %%eax    \n"
                "fstp       %%qword, %%eax  \n"
                "mov        $1, %%eax       \n"
                "jmp        short done      \n"
                "done:                      \n"
                :"=g"(root)
                :"g"(a), "g"(b), "g"(c)
                :"eax"
            );
        return(root);


int main(int argc, char **argv)

    double  a, b, c;
    double  root, rootC;

    printf("CS201 - Assignment 2p - Hayley Howard\n");  // print your own name instead
    if (argc != 4)
    
        printf("need 3 arguments: a, b, c\n");
        return -1;
    
    a = atof(argv[1]);
    b = atof(argv[2]);
    c = atof(argv[3]);
    root = quadraticRoot(a, b, c);
    rootC = quadraticRootC(a, b, c);

    printf("quadraticRoot(%.3f, %.3f, %.3f) = %.3f, %.3f\n", a, b, c, root, rootC);

    return 0;

【问题讨论】:

【参考方案1】:

如果你想在内联 asm 中使用符号名,你需要在你的约束中重新定义它们:

: [root] "=g"(root)
: [a] "g"(a), [b] "g"(b), [c] "g"(c)

然后在您的代码中引用它们,您可以使用 %[root]、%[a] 等。就我自己而言,我发现名称比 %0、%1 等更容易阅读。此外,在开发过程中/testing 你可能会添加/删除参数,这将迫使你重新处理 asm 中的所有操作数,这真的很痛苦。

更多详情请见here。

【讨论】:

【参考方案2】:

您应该使用操作数编号,而不是在内联汇编程序中的名称。只需将%root 替换为%0,将%a 替换为%1,将%b 替换为%2 等等。

查看here了解更多详情。

【讨论】:

以上是关于扩展内联汇编 gcc - 计算二次公式根的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有扩展内联 asm 的情况下在 gcc 内联汇编中声明和初始化局部变量?

优化系列汇编优化技术:x86架构内联汇编及demo

gcc 内联汇编行为异常

这个 GCC 内联汇编中的参数列表有啥问题?

GCC 内联汇编到 IAR 内联汇编

内联汇编