I'm writing a program using assembly code to write a program that calculate one of the quadratic equation roots. I've written all of my code, but I have the following error:
我正在编写一个程序,使用汇编代码编写一个计算二次方程根之一的程序。我已经编写了所有代码,但是我有以下错误:
main.c:37: Error: bad register name `%qword'
main.c:39: Error: junk `done' after expression
How do I correct those error, please?
请问如何纠正这些错误?
My codes is:
我的代码是:
// 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, 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;
}
The line where the error occurs:
发生错误的行:
"mov %0, %%eax \n"
"fstp %%qword, %%eax \n"
"mov $1, %%eax \n"
Any help would be appreciated.
任何帮助,将不胜感激。
1 个解决方案
#1
Apart from the errors you listed, there were some other issues. The main one being that the default operand size for fld
is single precision, while you have doubles. So you need to explicitly use fldl
. Second, if you ever find yourself using g
constraint, think twice, because chances are you are doing something wrong. In this case, the input operands should be memory references (m
constraint), and the output should be left in the FPU stack (t
constraint). I have removed the unused code dealing with the status word for now, I suppose that is a placeholder to detect taking the square root of a negative number.
除了您列出的错误外,还有其他一些问题。主要的一个是fld的默认操作数大小是单精度,而你有两倍。所以你需要明确地使用fldl。其次,如果你发现自己使用g约束,请三思而后行,因为你有可能做错了什么。在这种情况下,输入操作数应该是内存引用(m约束),输出应保留在FPU堆栈中(t约束)。我暂时删除了处理状态字的未使用代码,我想这是一个占位符来检测取负数的平方根。
You should always comment your code, but especially if you ask others for help. Since you haven't done that, I have no idea what you wanted to do with eax
at the end. I removed that too.
您应该始终评论您的代码,尤其是在您向其他人寻求帮助时。既然你没有这样做,我不知道你最后想用eax做什么。我也删除了它。
Here is a working version:
这是一个工作版本:
#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, 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
Apart from the errors you listed, there were some other issues. The main one being that the default operand size for fld
is single precision, while you have doubles. So you need to explicitly use fldl
. Second, if you ever find yourself using g
constraint, think twice, because chances are you are doing something wrong. In this case, the input operands should be memory references (m
constraint), and the output should be left in the FPU stack (t
constraint). I have removed the unused code dealing with the status word for now, I suppose that is a placeholder to detect taking the square root of a negative number.
除了您列出的错误外,还有其他一些问题。主要的一个是fld的默认操作数大小是单精度,而你有两倍。所以你需要明确地使用fldl。其次,如果你发现自己使用g约束,请三思而后行,因为你有可能做错了什么。在这种情况下,输入操作数应该是内存引用(m约束),输出应保留在FPU堆栈中(t约束)。我暂时删除了处理状态字的未使用代码,我想这是一个占位符来检测取负数的平方根。
You should always comment your code, but especially if you ask others for help. Since you haven't done that, I have no idea what you wanted to do with eax
at the end. I removed that too.
您应该始终评论您的代码,尤其是在您向其他人寻求帮助时。既然你没有这样做,我不知道你最后想用eax做什么。我也删除了它。
Here is a working version:
这是一个工作版本:
#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, 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;
}