c语言 - 扩展内联程序集 GCC - 编译时表达式错误后错误的寄存器名称和垃圾'done'



我正在使用汇编代码编写程序来编写一个计算二次方程根之一的程序。我已经编写了所有代码,但是我有以下错误:

main.c:37: Error: bad register name `%qword'
main.c:39: Error: junk `done' after expression

我该如何纠正这些错误?

我的代码是:

// function for checking that 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)
{
    double root;
    asm(
        "fld        %1              n"
        "fadd       %%ST            n"
        "fld        %1              n"
        "fld        %3              n"
        "fmulp      %%ST(1)         n"
        "fadd       %%ST            n"
        "fadd       %%ST            n"
        "fchs                       n"
        "fld        %2              n"
        "fld        %2              n"
        "fmulp      %%ST(1)         n"
        "faddp      %%ST(1)         n"
        "ftst                       n"
        "fstsw      %%1X            n"
        "sahf                       n"
        "fsqrt                      n"
        "fld        %2              n"
        "fchs                       n"
        "fdivp      %%ST(1)         n"
        "mov        %0, %%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;
    if (argc != 4) {
        printf("need 3 arguments: a, b, cn");
        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, %.3fn", a, b, c, root, rootC);
    return 0;
}

发生错误的线:

"mov        %0, %%eax    n"
"fstp       %%qword, %%eax  n"
"mov        $1, %%eax       n"

任何帮助将不胜感激。

除了您列出的错误,还有其他问题。主要的是,fld的默认操作数大小是单个精度,而您的双打是双重的。因此,您需要明确使用fldl。其次,如果您发现自己使用g约束,请三思而后行,因为您可能做错了什么。在这种情况下,输入操作数应为内存参考(m约束),并且输出应保留在FPU堆栈中(t约束)。我暂时删除了未使用的代码,目前涉及状态词,我想这是一个占位符,可以检测到负数的平方根。

您应该始终评论您的代码,但尤其是如果您向其他人寻求帮助。由于您没有这样做,所以我不知道您想对eax做什么。我也删除了。

这是一个工作版本:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// function for checking that 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)
{
    double root;
    asm(
        "fldl       %1       # a                   n"
        "fadd       %%ST     # 2a                  n"
        "fldl       %1       # a 2a                n"
        "fldl       %3       # c a 2a              n"
        "fmulp      %%ST(1)  # ac 2a               n"
        "fadd       %%ST     # 2ac 2a              n"
        "fadd       %%ST     # 4ac 2a              n"
        "fldl       %2       # b 4ac 2a            n"
        "fldl       %2       # b b 4ac 2a          n"
        "fmulp      %%ST(1)  # b^2 4ac 2a          n"
        "fsubp      %%ST(1)  # b^2-4ac 2a          n"
        "fsqrt               # sqrt(b^2-4ac) 2a    n"
        "fldl       %2       # b sqrt(b^2-4ac) 2a  n"
        "fchs                # -b sqrt(b^2-4ac) 2a n"
        "faddp      %%ST(1)  # -b+sqrt(b^2-4ac) 2a n"
        "fdivp      %%ST(1)  # -b+sqrt(b^2-4ac)/2a n"
        :"=t"(root)
        :"m"(a), "m"(b), "m"(c)
        );
    return(root);
}
int main(int argc, char **argv)
{
    double  a, b, c;
    double  root, rootC;
    if (argc != 4) {
        printf("need 3 arguments: a, b, cn");
        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, %.3fn", a, b, c, root, rootC);
    return 0;
}

最新更新